-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Snake is now a function which returns Either.
This is part of fix to #5. + Added new method to Snake interface: map + Added type alias SnakeFunc + Added new method liftSnake + Updated tfSnake method + Update snake method + Added new errorSnake method - Removed compose method
- Loading branch information
1 parent
98b043b
commit 59c2640
Showing
1 changed file
with
42 additions
and
16 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,63 @@ | ||
import { Observable, OperatorFunction, UnaryFunction } from "rxjs"; | ||
import { isNullOrUndefined } from "util"; | ||
import { Either, Right, Left } from "./Either"; | ||
|
||
/** | ||
* A Snake is an OperatorFunction that can be chained with another OperatorFunction | ||
* to produce a new Snake with a different return value. | ||
* A Snake is a unique operator function which creates a disjoint stream. It is capable of composing itself with other | ||
* OperatorFunctions through the use of `map` or other `Snakes` through the use of `chain`. | ||
* | ||
* Because snakes build individually on each other, this creates a type-safe method | ||
* of passing in a series of operator functions. | ||
* | ||
* ... This is just a Functor, isn't it? | ||
*/ | ||
export interface Snake<T, R> extends OperatorFunction<T, R> { | ||
chain<N>(op: OperatorFunction<R, N>) : Snake<T, N> | ||
export interface Snake<I, E, R> { | ||
(o: Observable<I>): Either<Observable<E>, Observable<R>> | ||
|
||
map<N>(op: OperatorFunction<R, N>) : Snake<I, E, N> | ||
chain<N>(s: Snake<R, E, N>): Snake<I, E, N> | ||
} | ||
|
||
function compose<A, B, C>(f1: UnaryFunction<A, B>, f2: UnaryFunction<B, C>): UnaryFunction<A, C> { | ||
return (a: A) => f2(f1(a)); | ||
export type SnakeFunc<I, E, R> = (i: Observable<I>) => Either<Observable<E>, Observable<R>>; | ||
|
||
/** | ||
* Lifts a normal function matching Snake to a real Snake. | ||
*/ | ||
export function liftSnake<I, E, R>(f: SnakeFunc<I, E, R>): Snake<I, E, R> { | ||
const rv: Snake<I, E, R> = (o: Observable<I>) => f(o); | ||
|
||
rv.map = <N>(f: OperatorFunction<R, N>) => | ||
liftSnake((i: Observable<I>) => rv(i).map(f)); | ||
|
||
rv.chain = <N>(s: Snake<R, E, N>) => | ||
liftSnake((i: Observable<I>) => rv(i).chain(s)); | ||
|
||
return rv; | ||
} | ||
|
||
/** | ||
* Takes an OperatorFunction and transforms it into a Snake. | ||
* @param op | ||
*/ | ||
export function tfSnake<T, R>(op: OperatorFunction<T, R>): Snake<T, R> { | ||
const rv: Snake<T, R> = (o: Observable<T>) => op(o); | ||
rv.chain = <N>(f: OperatorFunction<R, N>) => tfSnake(compose(rv, f)); | ||
export function tfSnake<I, E, R>(op: OperatorFunction<I, R>): Snake<I, E, R> { | ||
const rv: Snake<I, E, R> = (o: Observable<I>) => new Right(op(o)); | ||
|
||
rv.map = <N>(f: OperatorFunction<R, N>) => | ||
liftSnake((i: Observable<I>) => rv(i).map(f)); | ||
|
||
rv.chain = <N>(s: Snake<R, E, N>) => | ||
liftSnake((i: Observable<I>) => rv(i).chain(s)); | ||
|
||
return rv; | ||
} | ||
|
||
/** | ||
* Creates a new snake from the OperatorFunction. If no operator function is passed, | ||
* then an "indentity Snake" is created. | ||
* Creates a new "identity snake". | ||
*/ | ||
export function snake<I, E, R>(r: Observable<R>): Snake<I, E, R> { | ||
return liftSnake(() => new Right(r)); | ||
} | ||
|
||
/** | ||
* Creates a new "error snake". | ||
*/ | ||
export function snake<T, R = T>(op: OperatorFunction<T, R|T> = (t: Observable<T>) => t): Snake<T, R|T> { | ||
return tfSnake(op); | ||
export function errorSnake<I, E, R>(e: Observable<E>): Snake<I, E, R> { | ||
return liftSnake(() => new Left(e)); | ||
} |