2013-02-04 04:13:08 +00:00
|
|
|
/*! Either
|
|
|
|
!*/
|
|
|
|
|
2013-01-09 10:07:46 +00:00
|
|
|
|
|
|
|
Elm.Either = function() {
|
2013-02-04 04:13:08 +00:00
|
|
|
/*[Definition]*/
|
|
|
|
|
|
|
|
/** data Either a b = Left a | Right b
|
|
|
|
Represents any data that can take two different types.
|
|
|
|
|
|
|
|
This can also be used for error handling (`Either String a`) where
|
|
|
|
error messages are stored on the left, and the correct values
|
|
|
|
("right" values) are stored on the right.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function Left(a1) { return ['Left',a1]; }
|
|
|
|
function Right(a1){ return ['Right',a1]; }
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/*[Basics]*/
|
|
|
|
|
|
|
|
/** either : (a -> c) -> (b -> c) -> Either a b -> c
|
|
|
|
Apply the first function to a `Left` and the second function to a `Right`.
|
|
|
|
This allows the extraction of a value from an `Either`.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function either(f){ return function(g){ return function(e){
|
|
|
|
switch(e[0]){
|
|
|
|
case 'Left': return f(e[1]);
|
|
|
|
case 'Right': return g(e[1]);
|
|
|
|
}
|
|
|
|
};};}
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/** isLeft : Either a b -> Bool
|
|
|
|
True if the value is a `Left`.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function isLeft(e) { return e[0] == 'Left'; }
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/** isRight : Either a b -> Bool
|
|
|
|
True if the value is a `Right`.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function isRight(e) { return e[0] == 'Right'; }
|
|
|
|
|
2013-02-04 04:13:08 +00:00
|
|
|
/*[With Lists]*/
|
|
|
|
|
2013-01-09 10:07:46 +00:00
|
|
|
function get(es) { return Elm.List.map(function(x){return x[1];})(es); }
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/** lefts : [Either a b] -> [a]
|
|
|
|
Keep only the values held in `Left` values.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function lefts(es) { return get(Elm.List.filter(isLeft)(es)); }
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/** rights : [Either a b] -> [a]
|
|
|
|
Keep only the values held in `Right` values.
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function rights(es) { return get(Elm.List.filter(isRight)(es)); }
|
2013-02-04 04:13:08 +00:00
|
|
|
|
|
|
|
/** partition : [Either a b] -> ([a],[b])
|
|
|
|
Split into two lists, lefts on the left and rights on the right.
|
|
|
|
So we have the equivalence:
|
|
|
|
|
|
|
|
partition es == (lefts es, rights es)
|
|
|
|
**/
|
2013-01-09 10:07:46 +00:00
|
|
|
function partition(es) {
|
|
|
|
var lrs = Elm.List.partition(isLeft)(es);
|
|
|
|
lrs[1] = get(lrs[1]);
|
|
|
|
lrs[2] = get(lrs[2]);
|
|
|
|
return lrs;
|
|
|
|
}
|
|
|
|
return {Left:Left,
|
|
|
|
Right:Right,
|
|
|
|
either:either,
|
|
|
|
isLeft:isLeft,
|
|
|
|
isRight:isRight,
|
|
|
|
lefts:lefts,
|
|
|
|
rights:rights,
|
|
|
|
partition:partition};
|
|
|
|
}();
|