Skip to content

Instantly share code, notes, and snippets.

@bergmark
Last active August 29, 2015 14:20
Show Gist options
  • Save bergmark/f59e9b1de3b3d3e32b25 to your computer and use it in GitHub Desktop.
Save bergmark/f59e9b1de3b3d3e32b25 to your computer and use it in GitHub Desktop.
// x :: Either (Either a b) c -> Either a (Either b c)
// x = either (either Left (Right . Left)) (Right . Right)
interface Either<A,B> {
left? : A;
right? : B;
}
class Fns
{
static Left<A,B>(a : A) : Either<A,B>
{
return { left : a };
}
static Right<A,B>(b : B) : Either<A,B>
{
return { right : b };
}
static either<A,B,C>(f : (a : A) => C, g : (b : B) => C) : (v : Either<A,B>) => C
{
return function (v : Either<A,B>) : C
{
if (v.left !== undefined) return f(v.left );
if (v.right !== undefined) return g(v.right);
}
}
static cmp<A,B,C>(f : (b : B) => C, g : (a : A) => B) : (a : A) => C
{
return function (a : A) : C
{
return f(g(a));
};
}
static f<A,B,C>(v : Either<Either<A,B>,C>) : Either<A,Either<B,C>>
{
// Type error, but typechecks:
// return Fns.either(Fns.either(Fns.Left, Fns.cmp(Fns.Right, Fns.Left)), Fns.cmp(Fns.Right, Fns.Right));
// Correct, but doesn't type check:
// > Type 'Either<{}, {}>' is not assignable to type 'Either<A, Either<B, C>>'.
// > Type '{}' is not assignable to type 'A'.
// return Fns.either(Fns.either(Fns.Left, Fns.cmp(Fns.Right, Fns.Left)), Fns.cmp(Fns.Right, Fns.Right))(v);
// Works, too much typing needed to get it to actually type check.
return <Either<A,Either<B,C>>> Fns.either(Fns.either(Fns.Left, Fns.cmp(Fns.Right, Fns.Left)), Fns.cmp(Fns.Right, Fns.Right))(v);
// Should be something like this... type params for the cmp calls are wrong!
// return <Either<A,Either<B,C>>> Fns.either<Either<A,B>,C,Either<A,Either<B,C>>>(Fns.either<A,B,Either<A,Either<B,C>>>(Fns.Left, Fns.cmp<(x : Either<B,C>) => Either<A,Either<B,C>>, (x : C) => Either<B,C>, Either<A, Either<B,C>>>(Fns.Right, Fns.Left)), Fns.cmp<(x : Either<B,C>) => Either<A,Either<B,C>>, (x : C) => Either<B,C>, Either<A, Either<B,C>>>(Fns.Right, Fns.Right))(v);
}
};
console.log(Fns.f(Fns.Left(Fns.Left(1))));
console.log(Fns.f(Fns.Left(Fns.Right(2))));
console.log(Fns.f(Fns.Right(3)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment