From 31ef183ebf06b0feb7cca984883289aec532fb9e Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Thu, 11 Jan 2018 10:06:50 -0600 Subject: [PATCH 1/8] Add section on types --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/README.md b/README.md index c8a2dce..0ff476e 100644 --- a/README.md +++ b/README.md @@ -796,6 +796,50 @@ The `profunctor` method takes two arguments: 3. `promap` must return a value of the same Profunctor +## Types + +In Fantasy Land, types are specified by an object containing a catamorphic +method `cata`. `cata` has an arity matching the number of constructor functions +belonging to each type. Each argument to `cata` is either: + +1. a value +2. a function with an arity matching the number of arguments to the constructor + function. + 1. Each function argument to `cata` must return a value of the same type as + `cata` itself. + +ex. +```hs +Identity a = { cata :: (a -> b) -> b } +identity :: a -> Identity a +``` + +Libraries conforming to this specification may provide custom data constructors +corresponding with the constructor functions. No provided constructors are +required to share the names of the constructor functions defined herein. For +example, instead of `Identity`, the constructor could be named `Id`. If custom +constructors _are_ provided, they must return values which contain a `cata` +method. This method must exhibit the same behaviour as described above. + +ex. +```js +var identity = require('fantasy-land/identity'); + +function Id(x) { + this.x = x; +} +Id.prototype['fantasy-land/cata'] = function cata(f) { + return f(this.x); +} + +// Alternatively +Id.prototype['fantasy-land/cata'] = function cata(f) { + return identity(this.x).cata(f); +} + +(new Id(42)).cata(x => x) === identity(42).cata(x => x); +``` + ## Derivations When creating data types which satisfy multiple algebras, authors may choose From 8099a87af860b649049818ebbf094b77648c0297 Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Thu, 11 Jan 2018 10:07:38 -0600 Subject: [PATCH 2/8] Add Maybe specification --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 0ff476e..e8b19e1 100644 --- a/README.md +++ b/README.md @@ -840,6 +840,31 @@ Id.prototype['fantasy-land/cata'] = function cata(f) { (new Id(42)).cata(x => x) === identity(42).cata(x => x); ``` +### Maybe + +The `Maybe` type encodes the concept of optionality (Nothing and Just a). + +```hs +Maybe a = { cata :: (b, (a -> b)) -> b } +nothing :: Maybe a +just :: a -> Maybe a +``` + +A value which conforms to the Maybe specification must provide an `cata` method. + +The `cata` method takes two arguments: + + m.cata(x, f) + +1. `x` is the default value for the `Nothing` case + + 1. No parts of `x` should be checked. + +2. `f` must be a function which returns a value + + 1. If `f` is not a function, the behaviour of `cata` is unspecified. + 2. No parts of `f`'s return value should be checked. + ## Derivations When creating data types which satisfy multiple algebras, authors may choose From 935f2035b1d46e8b766aa1ae7b6cc2a9a489d8ef Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Thu, 11 Jan 2018 10:08:02 -0600 Subject: [PATCH 3/8] Add Either specification --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index e8b19e1..853e8b6 100644 --- a/README.md +++ b/README.md @@ -865,6 +865,32 @@ The `cata` method takes two arguments: 1. If `f` is not a function, the behaviour of `cata` is unspecified. 2. No parts of `f`'s return value should be checked. +### Either + +The `Either` type encodes the concept of binary possibility (Left a and Right b). + +```hs +Either a b = { cata :: ((a -> c), (b -> c)) -> c } +left :: a -> Either a b +right :: b -> Either a b +``` + +A value which conforms to the Either specification must provide an `cata` method. + +The `cata` method takes two arguments: + + e.cata(f, g) + +1. `f` must be a function which returns a value + + 1. If `f` is not a function, the behaviour of `cata` is unspecified. + 2. No parts of `f`'s return value should be checked. + +2. `g` must be a function which returns a value + + 1. If `g` is not a function, the behaviour of `cata` is unspecified. + 2. No parts of `g`'s return value should be checked. + ## Derivations When creating data types which satisfy multiple algebras, authors may choose From 15281ace35052288f043bc4f75af4222458a1d8a Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Thu, 11 Jan 2018 10:08:18 -0600 Subject: [PATCH 4/8] Add Tuple specification --- README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 853e8b6..86cedde 100644 --- a/README.md +++ b/README.md @@ -850,7 +850,7 @@ nothing :: Maybe a just :: a -> Maybe a ``` -A value which conforms to the Maybe specification must provide an `cata` method. +A value which conforms to the Maybe specification must provide a `cata` method. The `cata` method takes two arguments: @@ -875,7 +875,7 @@ left :: a -> Either a b right :: b -> Either a b ``` -A value which conforms to the Either specification must provide an `cata` method. +A value which conforms to the Either specification must provide a `cata` method. The `cata` method takes two arguments: @@ -891,6 +891,27 @@ The `cata` method takes two arguments: 1. If `g` is not a function, the behaviour of `cata` is unspecified. 2. No parts of `g`'s return value should be checked. +### Tuple + +`Tuple` is the canonical product type and represents a structure containing two +values (Tuple a b). + +```hs +Tuple a b = { cata :: ((a, b) -> c) -> c } +tuple :: (a, b) -> Tuple a b +``` + +A value which conforms to the Tuple specification must provide a `cata` method. + +The `cata` method takes a single argument: + + t.cata(f) + +1. `f` must be a function of two arguments which returns a value + + 1. If `f` is not a function, the behaviour of `cata` is unspecified. + 2. No parts of `f`'s return value should be checked. + ## Derivations When creating data types which satisfy multiple algebras, authors may choose From f5ddb0ba9a874eaf23d94c613befd1ff08cf0ed5 Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Mon, 15 Jan 2018 08:54:56 -0600 Subject: [PATCH 5/8] Clarify the description of arguments to cata --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86cedde..1ab28f0 100644 --- a/README.md +++ b/README.md @@ -802,10 +802,14 @@ In Fantasy Land, types are specified by an object containing a catamorphic method `cata`. `cata` has an arity matching the number of constructor functions belonging to each type. Each argument to `cata` is either: -1. a value -2. a function with an arity matching the number of arguments to the constructor - function. - 1. Each function argument to `cata` must return a value of the same type as +1. a value corresponding to a nullary constructor + + 1. Value arguments to `cata` must match the return type of `cata` itself. + +2. a function with an arity matching the number of arguments to the + corresponding constructor function + + 1. Function arguments to `cata` must return values of the same type as `cata` itself. ex. From 2e9e7fa94a9e0e4c557a0e77d4790fa6907fc0f9 Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Mon, 15 Jan 2018 08:59:38 -0600 Subject: [PATCH 6/8] Remove superfluous parentheses --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ab28f0..6dbcdfb 100644 --- a/README.md +++ b/README.md @@ -849,7 +849,7 @@ Id.prototype['fantasy-land/cata'] = function cata(f) { The `Maybe` type encodes the concept of optionality (Nothing and Just a). ```hs -Maybe a = { cata :: (b, (a -> b)) -> b } +Maybe a = { cata :: (b, a -> b) -> b } nothing :: Maybe a just :: a -> Maybe a ``` @@ -874,7 +874,7 @@ The `cata` method takes two arguments: The `Either` type encodes the concept of binary possibility (Left a and Right b). ```hs -Either a b = { cata :: ((a -> c), (b -> c)) -> c } +Either a b = { cata :: (a -> c, b -> c) -> c } left :: a -> Either a b right :: b -> Either a b ``` From 8b7dbd4a145b10dccf91047d933660899f6c5657 Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Mon, 15 Jan 2018 09:26:40 -0600 Subject: [PATCH 7/8] Add labels to type definition example --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6dbcdfb..217d6cc 100644 --- a/README.md +++ b/README.md @@ -812,10 +812,26 @@ belonging to each type. Each argument to `cata` is either: 1. Function arguments to `cata` must return values of the same type as `cata` itself. -ex. +For example ```hs Identity a = { cata :: (a -> b) -> b } +'------' ' '------' ' + ' ' ' ' - return type + ' ' ' + ' ' ' - destructor function + ' ' + ' ' - type variable + ' + ' - type name + identity :: a -> Identity a +'------' ' '--------' + ' ' ' + ' ' ' - return type + ' ' + ' ' - constructor argument + ' + ' - constructor name ``` Libraries conforming to this specification may provide custom data constructors @@ -825,7 +841,7 @@ example, instead of `Identity`, the constructor could be named `Id`. If custom constructors _are_ provided, they must return values which contain a `cata` method. This method must exhibit the same behaviour as described above. -ex. +For example ```js var identity = require('fantasy-land/identity'); From 78b714c750fb4031a4555f6a4ca4054b7806a83e Mon Sep 17 00:00:00 2001 From: Gabe Johnson Date: Mon, 15 Jan 2018 11:06:56 -0600 Subject: [PATCH 8/8] Update cata argument descriptions --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 217d6cc..6fb6693 100644 --- a/README.md +++ b/README.md @@ -874,16 +874,17 @@ A value which conforms to the Maybe specification must provide a `cata` method. The `cata` method takes two arguments: - m.cata(x, f) + m.cata(f, g) -1. `x` is the default value for the `Nothing` case +1. `f` must be a nullary function. It is called in the `Nothing` case - 1. No parts of `x` should be checked. + 1. If `f` is not a nullary function or the return value of `f` does not + match the return value of `cata`, the behaviour of `cata` is unspecified. -2. `f` must be a function which returns a value +2. `g` must be a unary function. It is called in the `Just` case - 1. If `f` is not a function, the behaviour of `cata` is unspecified. - 2. No parts of `f`'s return value should be checked. + 1. If `g` is not a unary function or the return value of `g` does not match + the return value of `cata`, the behaviour of `cata` is unspecified. ### Either @@ -901,15 +902,15 @@ The `cata` method takes two arguments: e.cata(f, g) -1. `f` must be a function which returns a value +1. `f` must be a unary function. It is called in the `Left` case - 1. If `f` is not a function, the behaviour of `cata` is unspecified. - 2. No parts of `f`'s return value should be checked. + 1. If `f` is not a unary function or the return value of `f` does not match + the return value of `cata`, the behaviour of `cata` is unspecified. -2. `g` must be a function which returns a value +2. `g` must be a unary function. It is called in the `Right` case - 1. If `g` is not a function, the behaviour of `cata` is unspecified. - 2. No parts of `g`'s return value should be checked. + 1. If `g` is not a unary function or the return value of `g` does not match + the return value of `cata`, the behaviour of `cata` is unspecified. ### Tuple @@ -927,10 +928,10 @@ The `cata` method takes a single argument: t.cata(f) -1. `f` must be a function of two arguments which returns a value +1. `f` must be a binary function - 1. If `f` is not a function, the behaviour of `cata` is unspecified. - 2. No parts of `f`'s return value should be checked. + 1. If `f` is not a binary function or the return value of `f` does not match + the return value of `cata`, the behaviour of `cata` is unspecified. ## Derivations