Add polymorphic type catamorphisms#280
Add polymorphic type catamorphisms#280gabejohnson wants to merge 3 commits intofantasyland:masterfrom
Conversation
|
So, Gabe and I have talked about this, and I thought it would be a good time to share a proposal I wrote on the back of a figurative beer mat about 6 months ago. Types are really simple, especially when church-encoded. Here are a bunch of them:
For all these types, there are well-defined instances for the various typeclasses:
So on, so forth. When reduced to Church encoding, everything has a nice, clean implementation that is as basic as it could possibly be. It is also enough of a structure to define all the implementations for all the spec. NOW, say I'm writing a library, I can write my library exactly how I like, with my own methods, never feeling pinned to a particular implementation of the spec. I can even worry about tail-recursion and the like by overriding the basic fold (providing that the new fold is indistinguishable to the user). I now have a common interface, which means values of my custom type will work with any other FL-compatible library. I now have my own methods, so I'm not restricted by a Fantasy Land implementation. This, to me, is the minimum possible structure we can require, while retaining all the utility. I have all the FL interfaces implemented, as well as the "constructors" for building church-encoded types, which I am then free to augment as I please. The point is that, whatever the situation, I know that a fantasy-land-compatible type has this My 2c, anyway. |
|
|
||
| Array.prototype['fantasy-land/identity'] = function identity(f) { | ||
| return f(this[0]); | ||
| }; |
There was a problem hiding this comment.
I don't think it's safe to define Array#fantasy-land/identity since [] exists.
There was a problem hiding this comment.
You are correct David. Perhaps identity isn't the right example to use.
There was a problem hiding this comment.
How about
function Some(x) {
this.x = x;
};
var None = {};
Some.prototype['fantasy-land/maybe'] = function maybe(_, f) {
return f(this.x);
};
None['fantasy-land/maybe'] = function maybe(d, _) {
return d;
};
Array.prototype['fantasy-land/maybe'] = function maybe(d, f) {
if (this.length === 0) return d;
return f(this[0]);
};
function maybe(d, f, m) {
return m['fantasy-land/maybe'](d, f);
}
var head = maybe.bind(null, None, Some);
var none = head([]);
none // None
var some = head([1, 2, 3]);
some // Some(1);
function fromMaybe(d, m) {
return maybe(d, x => x, m);
}
fromMaybe(0, none) // 0
fromMaybe(0, some) // 1?
Edit: Added maybe and fromMaybe for clarity
There was a problem hiding this comment.
I like that example, Gabe. 👍
78db20d to
e8b1678
Compare
As discussed in #151 (comment), #154 and #185 (comment), I propose a specification for
Eitherby providing a definition of a folding method namedeither.It isn't really a type specification, it's more of an interface or algebra specification as multiple structures could be isomorphic to
Eitherand hence provide aneithermethod.Open question: Should this specification be displayed in README.md, or in a type specific file?