Skip to content

Commit

Permalink
Version 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchambers committed Dec 24, 2016
1 parent 91c3737 commit 1e55dea
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# sanctuary-type-identifiers

A type is a set of values. Boolean, for example, is the type comprising
`true` and `false`. A value may be a member of multiple types (`42` is a
member of Number, PositiveNumber, Integer, and many other types).

In certain situations it is useful to divide JavaScript values into
non-overlapping types. The language provides two constructs for this
purpose: the [`typeof`][1] operator and [`Object.prototype.toString`][2].
Each has pros and cons, but neither supports user-defined types.

This package specifies an [algorithm][3] for deriving a _type identifier_
from any JavaScript value, and exports an implementation of the algorithm.
Authors of algebraic data types may follow this specification in order to
make their data types compatible with the algorithm.

### Algorithm

1. Take any JavaScript value `x`.

2. If `x` is `null` or `undefined`, go to step 6.

3. If `x.constructor` evaluates to `null` or `undefined`, go to step 6.

4. If `x.constructor.prototype === x`, go to step 6. This check prevents a
prototype object from being considered a member of its associated type.

5. If `typeof x.constructor['@@type']` evaluates to `'string'`, return
the value of `x.constructor['@@type']`.

6. Return the [`Object.prototype.toString`][2] representation of `x`
without the leading `'[object '` and trailing `']'`.

### Compatibility

For an algebraic data type to be compatible with the [algorithm][3]:

- every member of the type must have a `constructor` property pointing
to an object known as the _type representative_;

- the type representative must have a `@@type` property; and

- the type representative's `@@type` property (the _type identifier_)
must be a string primitive, ideally `'<npm-package-name>/<type-name>'`.

For example:

```javascript
// Identity :: a -> Identity a
function Identity(x) {
if (!(this instanceof Identity)) return new Identity(x);
this.value = x;
}

Identity['@@type'] = 'my-package/Identity';
```

Note that by using a constructor function the `constructor` property is set
implicitly for each value created. Constructor functions are convenient for
this reason, but are not required. This definition is also valid:

```javascript
// IdentityTypeRep :: TypeRep Identity
var IdentityTypeRep = {
'@@type': 'my-package/Identity'
};

// Identity :: a -> Identity a
function Identity(x) {
return {constructor: IdentityTypeRep, value: x};
}
```

### Usage

```javascript
var Identity = require('my-package').Identity;
var type = require('sanctuary-type-identifiers');

type(null); // => 'Null'
type(true); // => 'Boolean'
type([1, 2, 3]); // => 'Array'
type(Identity); // => 'Function'
type(Identity(0)); // => 'my-package/Identity'
```

[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
[3]: #algorithm
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sanctuary-type-identifiers",
"version": "0.0.0",
"version": "1.0.0",
"description": "Specification for type identifiers",
"license": "MIT",
"repository": {
Expand Down

1 comment on commit 1e55dea

@davidchambers
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look, @Avaq! The first release is v1.0.0! 😄

Please sign in to comment.