forked from gcanti/fp-ts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStateTaskEither.ts
110 lines (94 loc) · 3.27 KB
/
StateTaskEither.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { Either } from '../src/Either'
import { Monad3 } from '../src/Monad'
import { State } from '../src/State'
import * as stateT from '../src/StateT'
import { TaskEither, taskEither } from '../src/TaskEither'
import { Endomorphism } from '../src/function'
declare module '../src/HKT' {
interface URI2HKT3<U, L, A> {
StateTaskEither: StateTaskEither<U, L, A>
}
}
const stateTIO = stateT.getStateT(taskEither)
export const URI = 'StateTaskEither'
export type URI = typeof URI
export class StateTaskEither<S, L, A> {
readonly _A!: A
readonly _L!: L
readonly _U!: S
readonly _URI!: URI
constructor(readonly value: (s: S) => TaskEither<L, [A, S]>) {}
run(s: S): Promise<Either<L, [A, S]>> {
return this.value(s).run()
}
eval(s: S): Promise<Either<L, A>> {
return this.run(s).then(e => e.map(([a]) => a))
}
exec(s: S): Promise<Either<L, S>> {
return this.run(s).then(e => e.map(([_, s]) => s))
}
map<B>(f: (a: A) => B): StateTaskEither<S, L, B> {
return new StateTaskEither(stateTIO.map(f, this.value))
}
ap<B>(fab: StateTaskEither<S, L, (a: A) => B>): StateTaskEither<S, L, B> {
return new StateTaskEither(stateTIO.ap(fab.value, this.value))
}
ap_<B, C>(this: StateTaskEither<S, L, (b: B) => C>, fb: StateTaskEither<S, L, B>): StateTaskEither<S, L, C> {
return fb.ap(this)
}
chain<B>(f: (a: A) => StateTaskEither<S, L, B>): StateTaskEither<S, L, B> {
return new StateTaskEither(stateTIO.chain(a => f(a).value, this.value))
}
orElse<M>(f: (l: L) => StateTaskEither<S, M, A>): StateTaskEither<S, M, A> {
return new StateTaskEither(s => this.value(s).orElse(l => f(l).value(s)))
}
}
const map = <S, L, A, B>(fa: StateTaskEither<S, L, A>, f: (a: A) => B): StateTaskEither<S, L, B> => {
return fa.map(f)
}
const of = <S, L, A>(a: A): StateTaskEither<S, L, A> => {
return new StateTaskEither(stateTIO.of(a))
}
const ap = <S, L, A, B>(
fab: StateTaskEither<S, L, (a: A) => B>,
fa: StateTaskEither<S, L, A>
): StateTaskEither<S, L, B> => {
return fa.ap(fab)
}
const chain = <S, L, A, B>(
fa: StateTaskEither<S, L, A>,
f: (a: A) => StateTaskEither<S, L, B>
): StateTaskEither<S, L, B> => {
return fa.chain(f)
}
const stateTget = stateT.get(taskEither)
export const get = <L, S>(): StateTaskEither<S, L, S> => {
return new StateTaskEither<S, L, S>(stateTget())
}
const stateTput = stateT.put(taskEither)
export const put = <L, S>(s: S): StateTaskEither<S, L, void> => {
return new StateTaskEither<S, L, void>(stateTput(s))
}
const stateTmodify = stateT.modify(taskEither)
export const modify = <L, S>(f: Endomorphism<S>): StateTaskEither<S, L, void> => {
return new StateTaskEither<S, L, void>(stateTmodify(f))
}
const stateTgets = stateT.gets(taskEither)
export const gets = <S, L, A>(f: (s: S) => A): StateTaskEither<S, L, A> => {
return new StateTaskEither<S, L, A>(stateTgets(f))
}
const stateTliftF = stateT.liftF(taskEither)
export const fromTaskEither = <S, L, A>(fa: TaskEither<L, A>): StateTaskEither<S, L, A> => {
return new StateTaskEither(stateTliftF(fa))
}
const stateTfromState = stateT.fromState(taskEither)
export const fromState = <S, A, L>(fa: State<S, A>): StateTaskEither<S, L, A> => {
return new StateTaskEither(stateTfromState(fa))
}
export const stateTaskEither: Monad3<URI> = {
URI,
map,
of,
ap,
chain
}