-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documentation for Identity #330
Changes from 3 commits
566c922
597e3b8
588ce68
c19b3c0
246c005
d705062
7580bc6
ac78f8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
--- | ||
title: "Identity" | ||
description: "Identity Crock" | ||
layout: "guide" | ||
weight: 60 | ||
--- | ||
|
||
```haskell | ||
Identity a | ||
``` | ||
|
||
`Identity` is one of the most versatile `monads`. Although it does not have any | ||
inherant behaviour its power comes from lifting a simple value into the monadic | ||
space and applying the given `function` (`map`/`chain`/etc) to it's value. | ||
`Identity` is often used in place where a `monad` or `applicative` is expected. | ||
Identity is also known the "empty" functor and applicative functor. `Identity` | ||
composed with another functor or applicative functor is isomorphic to the | ||
original. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
Identity(10) | ||
//=> Identity 10 | ||
``` | ||
<article id="topic-implements"> | ||
|
||
## Implements | ||
`Setoid`, `Semigroup`, `Functor`, `Chain`, `Traversable`, `Apply`, `Applicative`, `Monad` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list need to be in order of constraints imposed, so:
|
||
|
||
</article> | ||
|
||
<article id="topic-construction"> | ||
|
||
## Construction | ||
|
||
```haskell | ||
Identity :: a -> Identity a | ||
``` | ||
|
||
The contstructor for an `Identity` is a unary function. When a value is passed | ||
in an `Identity` of the given value is returned ready for `map` or `chain`. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
const fromComputerCode = String.fromCharCode | ||
|
||
Identity(42) | ||
.map(fromComputerCode) | ||
//=> Identity '*' | ||
|
||
``` | ||
|
||
</article> | ||
|
||
<article id="topic-constructor"> | ||
|
||
## Constructor Methods | ||
|
||
#### of | ||
|
||
```haskell | ||
Identity.of :: a -> Identity a | ||
``` | ||
|
||
`of` is used to construct an `Identity` with any given value. It is there to | ||
allow `Identity` to function as a pointed functor. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
const { of } = Identity | ||
|
||
of(42) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use |
||
//=> Identity 42 | ||
|
||
of(true) | ||
//=> Identity true | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extra newline here, fences should hug the code tightly. |
||
``` | ||
|
||
</article> | ||
|
||
<article id="topic-instance"> | ||
|
||
## Instance Methods | ||
|
||
#### equals | ||
|
||
```haskell | ||
Identity a ~> b -> Boolean | ||
``` | ||
|
||
Used to compare the underlying values of two `Identity` instances for equality by | ||
value, `equals` takes any given argument and returns `true` if the passed | ||
arguments is a `Identity` with an underlying value equal to the underlying value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a |
||
of the `Identity` the method is being called on. If the passed argument is not | ||
an `Identity` or the underlying values are not equal, `equals` will return `false`. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
import equals from 'crocks/pointfree/equals' | ||
|
||
Identity(33) | ||
.equals(Identity(33)) | ||
//=> true | ||
|
||
Identity(33) | ||
.equals(Identity('33')) | ||
//=> false | ||
|
||
// by value, not reference for most types | ||
Identity({ a: 86, b: true }) | ||
.equals(Identity({ a: 86, b: true })) | ||
//=> true | ||
|
||
equals(Identity(95), 95) | ||
//=> false | ||
|
||
equals(Identity([ 2, 3 ]), Identity([ 2, 3 ])) | ||
//=> true | ||
``` | ||
|
||
#### concat | ||
|
||
```haskell | ||
Identity s => Identity s ~> Identity s -> Identity s | ||
``` | ||
|
||
When an underlying value of a given `Identity` is fixed to a `Semigroup`, | ||
`concat` can be used to concat another `Identity` instance with an underlying | ||
`Semigroup` of the same type. Expecting a `Identity` wrapping a `Semigroup` of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a |
||
the same type, `concat` will give back a new `Identity` instance wrapping the | ||
result of combining the two underlying `Semigroup`s. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
import Sum from 'crocks/Sum' | ||
|
||
import compose from 'crocks/helpers/compose' | ||
import concat from 'crocks/pointfree/concat' | ||
import flip from 'crocks/combinators/flip' | ||
import map from 'crocks/pointfree/map' | ||
import mapReduce from 'crocks/helpers/mapReduce' | ||
import valueOf from 'crocks/pointfree/valueOf' | ||
|
||
// empty :: Identity Sum | ||
const empty = | ||
Identity(Sum.empty()) | ||
|
||
// sumList :: [ * ] -> Identity Number | ||
const sumList = compose( | ||
map(valueOf), | ||
mapReduce(compose(Identity, Sum), flip(concat), empty) | ||
) | ||
|
||
Identity([ 34 ]) | ||
.concat(Identity([ 92 ])) | ||
//=> Identity [ 34, 92 ] | ||
|
||
sumList([ 3, 4, 5 ]) | ||
//=> Identity 12 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra newline (cinima) |
||
``` | ||
|
||
#### map | ||
|
||
```haskell | ||
Identity a ~> (a -> b) -> Identity b | ||
``` | ||
|
||
Used to apply transformations to values you've lifted into an `Identity`, `map` | ||
takes a function that it will lift into the context of the `Identity` and apply | ||
to it the wrapped value. `Identity` contains no bahaviour and will do nothing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bahaviour -> behavior |
||
more than apply the value inside the `Identity` to the function. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
import map from 'crocks/pointfree/map' | ||
|
||
const prod = a => b => a * b | ||
|
||
const mapDouble = map(prod(2)) | ||
|
||
mapDouble(Identity(5)) | ||
//=> Identity 10 | ||
``` | ||
|
||
#### ap | ||
|
||
```haskell | ||
Identity (a -> b) ~> Identity a -> Identity b | ||
``` | ||
|
||
`ap` allows for values wrapped in a `Identity` to be applied to functions also | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a |
||
wrapped in a `Identity`. In order to use `ap`, the `Identity` must contain a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a |
||
function as its value. Under the hood, `ap` unwraps both the function | ||
and the value to be applied and applies the value to the function. Finally it | ||
will wrap the result of that application back into a `Identity`. It is required | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a |
||
that the inner function is curried. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
const prod = a => b => a * b | ||
const double = prod(2) | ||
|
||
Identity(double) | ||
.ap(5) | ||
//=> Identity 10 | ||
|
||
``` | ||
|
||
#### sequence | ||
|
||
```haskell | ||
Apply f => Identity (f a) ~> (b -> f b) -> f (Identity a) | ||
Applicative f => Identity (f a) ~> TypeRep f -> f (Identity a) | ||
``` | ||
|
||
When an instance of `Identity` wraps an `Apply` instance, `sequence` can be used to | ||
swap the type sequence. `sequence` requires either an `Applicative TypeRep` or | ||
an `Apply` returning function is provided for its argument. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is provided -> to be provided There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This came from |
||
|
||
`sequence` can be derived from [`traverse`](#traverse) by passing it an | ||
`identity` function (`x => x`). | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
|
||
import Maybe from 'crocks/Maybe' | ||
import sequence from 'crocks/pointfree/sequence' | ||
|
||
// seqId :: Identity Maybe a -> Maybe Identity a | ||
const seqMaybe = | ||
sequence(Maybe) | ||
|
||
seqMaybe(Identity(Maybe(42))) | ||
//=> Just Identity 42 | ||
``` | ||
|
||
#### traverse | ||
|
||
#### chain | ||
|
||
```haskell | ||
Identity a ~> (a -> Identity b) -> Identity b | ||
``` | ||
|
||
Normally one of the ways `Monad`s like `Identity` are able to be combined and | ||
have their effects applied is through `chain`. However `Identity` is different | ||
because there are no effects to apply. `chain` will simply take a func that | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. func -> function |
||
returns `Identity` and applies it to its value. | ||
|
||
```javascript | ||
import Identity from 'crocks/Identity' | ||
import compose from 'crocks/helpers/compose' | ||
import chain from 'crocks/pointfree/chain' | ||
|
||
const prod = a => b => a * b | ||
const doubleAsIdentity = compose(Identity, prod(2)) | ||
|
||
doubleAsIdentity(21) | ||
//=> Identity 42 | ||
|
||
chain(doubleAsIdentity, Identity(5)) | ||
//=> Identity 10 | ||
|
||
``` | ||
|
||
</article> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ names, but what they do from type to type may vary. | |
| [`Const`][const] | -- | [`ap`][const-ap], [`chain`][const-chain], [`concat`][const-concat], [`equals`][const-equals], [`map`][const-map], [`valueOf`][const-valueof] | | ||
| [`Either`][either] | [`Left`][either-left], [`Right`][either-right], [`of`][either-of]| [`alt`][either-alt], [`ap`][either-ap], [`bimap`][either-bimap], [`chain`][either-chain], [`coalesce`][either-coalesce], [`concat`][either-concat], [`either`][either-either], [`equals`][either-equals], [`map`][either-map], [`of`][either-of], [`sequence`][either-sequence], [`swap`][either-swap], [`traverse`][either-traverse] | | ||
| [`Equiv`][equiv] | [`empty`][equiv-empty] | [`concat`][equiv-concat], [`contramap`][equiv-contra], [`compareWith`][equiv-compare], [`valueOf`][equiv-value] | | ||
| `Identity` | `of` | `ap`, `chain`, `concat`, `equals`, `map`, `of`, `sequence`, `traverse`, `valueOf` | | ||
| [`Identity`][identity] | [`of`][identity-of] | [`ap`][identity-ap], [`chain`][identity-chain], [`concat`][identity-concat], [`equals`][identity-equals], [`map`][identity-map], [`of`][identity-of], [`sequence`][identity-sequence], [`traverse`][identity-traverse], [`valueOf`][identity-valueOf] | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. link refs should be all lowercase: identity-valueOf -> identity-valueof also missing the identity-valueof ref below. |
||
| `IO` | `of` | `ap`, `chain`, `map`, `of`, `run` | | ||
| `List` | `empty`, `fromArray`, `of` | `ap`, `chain`, `concat`, `cons`, `empty`, `equals`, `filter`, `fold`, `foldMap`, `head`, `map`, `of`, `reduce`, `reduceRight`, `reject`, `sequence`, `tail`, `toArray`, `traverse`, `valueOf` | | ||
| [`Maybe`][maybe] | [`Nothing`][maybe-nothing], [`Just`][maybe-just], [`of`][maybe-of], [`zero`][maybe-zero] | [`alt`][maybe-alt], [`ap`][maybe-ap], [`chain`][maybe-chain], [`coalesce`][maybe-coalesce], [`concat`][maybe-concat], [`equals`][maybe-equals], [`either`][maybe-either], [`map`][maybe-map], [`of`][maybe-of], [`option`][maybe-option], [`sequence`][maybe-sequence], [`traverse`][maybe-traverse], [`zero`][maybe-zero] | | ||
|
@@ -95,6 +95,17 @@ names, but what they do from type to type may vary. | |
[either-swap]: Either.html#swap | ||
[either-traverse]: Either.html#traverse | ||
|
||
[identity]: Identity.html | ||
[identity-of]: Identity.html#of | ||
[identity-alt]: Identity.html#alt | ||
[identity-ap]: Identity.html#ap | ||
[identity-chain]: Identity.html#chain | ||
[identity-concat]: Identity.html#concat | ||
[identity-equals]: Identity.html#equals | ||
[identity-map]: Identity.html#map | ||
[identity-sequence]: Identity.html#sequence | ||
[identity-traverse]: Identity.html#traverse | ||
|
||
[equiv]: Equiv.html | ||
[equiv-empty]: Equiv.html#empty | ||
[equiv-concat]: Equiv.html#concat | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worried that this may be to much and going a little to deep on the Category Theory for the average learner.
Could the description be something like:
Identity
is acrock
that can be used to wrap a common interface around existing Javascript types and functions. It maintains integrity by lifting and applying functions and types as is, without adding any additional structure or effects. By not applying and additional structure to existing functions,Identity
can be swapped in and out for otherFunctor
s that do apply their own structure and effects.Or something along those lines. Talk more about usage, then theory. Still give a little theory to put it in context with the other types, but focus more on its usage in the grand scheme of things. Without giving away too much.
(boy that is a wishy-washy suggestion)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha all good. Never thought the roles would be reversed and you'd tell me i was being too theoretical :)