Created
November 19, 2016 14:24
-
-
Save trknhr/e7318cd38f160237089b05304fb39de6 to your computer and use it in GitHub Desktop.
This file contains 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
export abstract class Either<T, U>{ | |
abstract isRight(): boolean; | |
abstract fold<X>(l: (t: T) => X, r: (u: U) => X): X; | |
isLeft(): boolean{ | |
return !this.isRight(); | |
} | |
map<B>(f: (U) => B): Either<T, B>{ | |
return this.fold( | |
(l) => <Either<T, B>><any> this, (r) => new Right(f(r)) | |
) | |
} | |
flatMap<B>(f: (U) => Either<T, B>): Either<T, B>{ | |
return this.fold( | |
(l) => <Either<T, B>><any> this, (r) => f(r) | |
) | |
} | |
map2<B, C>(b: Either<T, B>, f: (a: U, b: B) => C): Either<T, C>{ | |
return this.fold( | |
(l) => <Either<T, C>><any> this, (r) => b.flatMap((bb) => new Right(f(r, bb))) | |
) | |
} | |
} | |
export class Left<T, U> extends Either<T, never>{ | |
constructor(private t: T){ | |
super() | |
} | |
isRight(): boolean{ | |
return false; | |
} | |
fold<X>(l: (t: T) => X, r: (u: U) => X): X{ | |
return l(this.t); | |
} | |
} | |
export class Right<T, U> extends Either<never, U>{ | |
constructor(private u: U ){ | |
super() | |
} | |
isRight(): boolean{ | |
return true; | |
} | |
fold<X>(l: (t: T) => X, r: (u: U) => X): X{ | |
return r(this.u); | |
} | |
} |
This file contains 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
import {Either, Right, Left} from './Either' | |
type Name = string; | |
type Age = number; | |
type Person = {readonly name: Name, readonly age: Age }; | |
const mkName = (name: string): Either<string, Name> => { | |
if(name === "" || name == null) return new Left("Name is empty") | |
else return new Right<string, Name>(name) | |
} | |
const mkAge = (age: number): Either<string, Age> => { | |
if(age < 0) return new Left("Age is out of range") | |
else return new Right<string, Age>(age) | |
} | |
const mkPerson = (name: string, age: number): Either<string, Person> => mkName(name).map2(mkAge(age), (a,b) => {return {name: a, age: b}}) | |
console.log(mkAge(9)) | |
console.log(mkAge(-99)) | |
console.log(mkName("knhr__")) | |
console.log(mkName(null)) | |
console.log(mkPerson("knhr__", -99)) | |
console.log(mkPerson("", 99)) | |
console.log(mkPerson("knhr__", 27)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment