Skip to content
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

improving definitions for monoid, comonad, applicative, and ADT #230

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 26 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ One simple monoid is the addition of numbers:
```
In this case number is the object and `+` is the function.

When any value is combined with the "identity" value the result must be the original value. The identity must also be commutative.
When any value of the monoid is combined with the "identity" value the result must be the original value. Combining with identity must also be commutative.

The identity value for addition is `0`.
```js
Expand Down Expand Up @@ -693,14 +693,16 @@ Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['

## Comonad

An object that has `extract` and `extend` functions.
An object that has `extract` and `extend` functions. `extract` is the dual (opposite) of `of` from [Pointed Functor](#pointed-functor) and `extend` is the dual of `chain` from [Monad](#monad)

```js
const CoIdentity = (v) => ({
val: v,
// extract :: CoIdentity a ~> () -> a
extract () {
return this.val
},
// extract :: CoIdentity a ~> (CoIdentity a -> CoIdentity b) -> CoIdentity b
extend (f) {
return CoIdentity(f(this))
}
Expand Down Expand Up @@ -764,10 +766,10 @@ Array.prototype.ap = function (xs) {
}

// Example usage
;[(a) => a + 1].ap([1]) // [2]
Array.of((a) => a + 1).ap([1]) // [2]
```

This is useful if you have two objects and you want to apply a binary function to their contents.
This is useful if you have two objects and you want to apply a [binary](#arity) [curried](#currying) function to their contents.

```js
// Arrays that you want to combine
Expand All @@ -786,6 +788,17 @@ This gives you an array of functions that you can call `ap` on to get the result
partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8]
```

Using [Option](#option):

```ts
some(1).map(add).ap(some(2)) // some(3)

none.map(add).ap(some(2)) // none

```

Note that `some(1).map(add).ap(some(2))` is equivalent to `some(add).ap(some(1)).ap(some(2))`. The difference is whether the argument is [lifted](#lift) first or the binary function. You can look at `.ap` like the function call syntax for functions that are inside of [functors](#functor).

## Morphism

A relationship between objects within a [category](#category). In the context of functional programming all functions are morphisms.
Expand Down Expand Up @@ -1076,7 +1089,15 @@ A **product** type combines types together in a way you're probably more familia
// point :: (Number, Number) -> {x: Number, y: Number}
const point = (x, y) => ({ x, y })
```
It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type.
It's called a product because the total possible values of the data structure is the product of the different values.

```ts
type Rank = 'A' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | 'J' | 'Q' | 'K'
Copy link
Owner

Choose a reason for hiding this comment

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

Any other alternatives? @jethrolarson 🤓

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Infinitely many, but why?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I figured playing cards were something that a lot of people are familiar with whose instances are a product of two sets.

Copy link
Owner

Choose a reason for hiding this comment

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

I meant instead of using ts :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, it's a concept that only exists in type space so some kind of type syntax is necessary to describe it. Hmm I don't know how this would be represented in the pseudo-type system this document uses.

In F# which is a hindley-milner system it'd be something like

type Rank = A | Two | Three  | Four | Five | Six | Seven | Eight | Nine | Ten | J | Q | K
type Suit = Spades | Hearts | Clubs | Diamonds
type Card = Rank * Suit

Is that better?

Copy link
Owner

Choose a reason for hiding this comment

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

hindley-milner for consistence, sure! Thanks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My reticence is then that these named types have no representation in value-space and thus may make no sense in JS.

Copy link
Owner

Choose a reason for hiding this comment

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

nods, but hindley-milner would be bit more consistent?

type Suit = '♠' | '♥' | '♣' | '♦'
type Card = {rank: Rank, suit: Suit}
```
In the above, `Card` is a type which is the product of `Rank` and `Suit` which leads to 52 possibilities (13 Ranks x 4 suits = 52 cards)


See also [Set theory](https://en.wikipedia.org/wiki/Set_theory).

Expand Down