Created
May 12, 2017 18:41
-
-
Save i-am-tom/7fe569af2c80218f4b50e4c9a6687007 to your computer and use it in GitHub Desktop.
A Fantasy Land-Compliant Rose Tree.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fl = require('fantasy-land') | |
//- Textbook rose tree. | |
//+ type RoseTree a = { value :: a, children :: [RoseTree a] } | |
function RoseTree(value, children) { | |
if (this.constructor !== RoseTree) | |
return new RoseTree(value, children) | |
Object.assign(this, { value, children }) | |
} | |
/* Setoid a => Setoid (RoseTree a) */ { | |
RoseTree.prototype[fl.equals] = function ({ value, children }) { | |
return this.value[fl.equals](value) | |
&& this.children.length === children.length | |
&& this.children.every((child, i) => | |
child[fl.equals](children[i])) | |
} | |
} | |
/* Ord a => Ord (RoseTree a) */ { | |
RoseTree.prototype[fl.lte] = function ({ value, children }) { | |
return this.value[fl.lte](value) | |
? this.value[fl.equals](value) | |
? this.children[fl.lte](children) | |
: true | |
: false | |
} | |
} | |
/* Functor RoseTree */ { | |
RoseTree.prototype[fl.map] = function (f) { | |
return RoseTree(f(this.value), this.children.map(f)) | |
} | |
} | |
/* Apply RoseTree */ { | |
RoseTree.prototype[fl.ap] = function ({ value: f, children: fs }) { | |
const { value: x, children: xs } = this | |
return RoseTree(f(x), [].concat( | |
xs.map(x => x.map(f)), | |
fs.map(f => this.value.ap(f)) | |
)) | |
} | |
} | |
/* Applicative RoseTree */ { | |
RoseTree[fl.of] = x => RoseTree(x, []) | |
} | |
/* Foldable RoseTree */ { | |
RoseTree.prototype[fl.reduce] = function (f, acc) { | |
return this.children.reduce( | |
(acc, rt) => rt[fl.reduce](f, acc), | |
f(acc, this.value)) | |
} | |
} | |
/* Traversable RoseTree */ { | |
RoseTree.prototype[fl.traverse] = function (T, f) { | |
return this.children[fl.traverse](T, f)[fl.ap]( | |
f(this.value).map(v => cs => RoseTree(v, cs)) | |
) | |
} | |
} | |
/* Chain RoseTree */ { | |
RoseTree.prototype[fl.chain] = function (f) { | |
const { value: x, children: xs } = f(this.value) | |
return RoseTree(x, [].concat(xs, | |
this.children.map(x => x[fl.chain](f)) | |
)) | |
} | |
} | |
/* Extend RoseTree */ { | |
RoseTree.prototype[fl.extend] = function (f) { | |
return RoseTree(f(this), this.children.map(x => x[fl.extend](f))) | |
} | |
} | |
/* Comonad RoseTree */ { | |
RoseTree.prototype[fl.extract] = function () { | |
return this.value | |
} | |
} | |
module.exports = RoseTree |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment