Skip to content

Instantly share code, notes, and snippets.

@rpominov
Last active November 5, 2016 10:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rpominov/6b4462137aff8de92dbd078da6a3564c to your computer and use it in GitHub Desktop.
Save rpominov/6b4462137aff8de92dbd078da6a3564c to your computer and use it in GitHub Desktop.
Example of use of the new approach for fantasy-land

This is an example of use of the new approach for fantasy-land proposed in fantasyland/fantasy-land#199

Read this commnet to understand what "Spec compatible Type Representative" and "spec compatible value" means.

// This module exposes Representative that produces spec compatible values.
const Maybe = {
of(x) {
return {
'fantasy-land': Maybe,
type: 'just',
value: x,
}
},
nothing: {
'fantasy-land': Maybe,
type: 'nothing',
},
map(f, v) {
return v.type === 'nothing' ? v : Maybe.of(f(v.value))
},
ap(f, v) {
return f.type === 'nothing' ? f : (v.type === 'nothing' ? v : Maybe.of(f.value(v.value)))
},
}
export {Maybe}
// This module also exposes Representative that produces spec compatible values
// but uses JavaScript classes under the hood.
function IdC(x) {
this._x = x
}
const Id = {
of(x) {
return new IdC(x)
},
map(f, v) {
return new IdC(f(v._x))
},
ap(f, v) {
return new IdC(f._x(v._x))
}
}
IdC.prototype['fantasy-land'] = Id
export {Id}
// Unlike in maybe.js and id.js in this module we expose Representatives
// that produce spec _incompatible_ values but Representatives themselves are compatible.
const List = {
of(x) {return [x]},
map(f, v) {return v.map(f)},
ap(f, v) {return f.map(f => v.map(f)).reduce((r, i) => r.concat(i), [])},
}
const ZipList = {
of(x) {return [x]},
map(f, v) {return v.map(f)},
ap(f, v) {return f.map((f, i) => f(v[i]))},
}
export {List, ZipList}
// In this module we write code that works with spec compatible values.
// We don't have to pass Representatives around, but all values must have `fantasy-land` property.
import {Id} from 'id'
import {Maybe} from 'maybe'
// Generic code
function lift2(f, a, b) {
const T = a['fnatasy-land']
return T.ap(T.map(a => b => f(a, b), a), b)
}
// App code
lift2((a, b) => a + b, Id.of(1), Id.of(2)) // Id.of(3)
lift2((a, b) => a + b, Maybe.of(1), Maybe.nothing) // Maybe.nothing
// In this module we write code that works with spec compatible Type Representatives.
// We can use array.js here as well as maybe.js and id.js.
import {List, ZipList} from 'array'
import {Maybe} from 'maybe'
// Generic code
function lift2(T, f, a, b) {
return T.ap(T.map(a => b => f(a, b), a), b)
}
// App code
lift2(Id, (a, b) => a + b, Id.of(1), Id.of(2)) // Id.of(3)
lift2(List, (a, b) => a + b, [1, 2], [3, 4]) // [3, 5, 5, 6]
lift2(ZipList, (a, b) => a + b, [1, 2], [3, 4]) // [3, 6]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment