Skip to content

Instantly share code, notes, and snippets.

@mrtnbroder
Forked from i-am-tom/RoseTree.js
Created November 1, 2018 09:04
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 mrtnbroder/b65cdff54f26cf180f3fc7938f86cb93 to your computer and use it in GitHub Desktop.
Save mrtnbroder/b65cdff54f26cf180f3fc7938f86cb93 to your computer and use it in GitHub Desktop.
A Fantasy Land-Compliant Rose Tree.
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