Skip to content

Commit f2f5034

Browse files
committed
refactor(either): rename Exit to Either
Either need not be internal to this project. BREAKING CHANGE: `Exit` is renamed to `Either`
1 parent 6c4aab6 commit f2f5034

File tree

11 files changed

+195
-94
lines changed

11 files changed

+195
-94
lines changed

index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* tslint:disable:file-name-casing */
22
export {Await} from './src/main/Await'
3-
export {Exit} from './src/main/Exit'
3+
export {Either} from './src/main/Either'
44
export {Fiber} from './src/main/Fiber'
55
export {FIO, IO, Task, TaskR, UIO} from './src/main/FIO'
66
export {FStream, Stream} from './src/main/FStream'

src/internals/Coordinate.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Await} from '../main/Await'
2-
import {Exit} from '../main/Exit'
2+
import {Either} from '../main/Either'
33
import {Fiber} from '../main/Fiber'
44
import {FIO, UIO} from '../main/FIO'
55
import {Ref} from '../main/Ref'
@@ -10,22 +10,25 @@ import {Ref} from '../main/Ref'
1010
* @ignore
1111
*/
1212
export const coordinate = <E1, A1, E2, A2>(
13-
exit: Exit<E1, A1>,
13+
exit: Either<E1, A1>,
1414
fiber: Fiber<E2, A2>,
15-
ref: Ref<Exit<E1, A1>>,
15+
ref: Ref<Either<E1, A1>>,
1616
count: Ref<number>,
1717
await: Await<never, boolean>
1818
): UIO<boolean> =>
1919
ref
2020
.set(exit)
2121
.chain(e =>
22-
Exit.isFailure(e)
23-
? fiber.abort.and(await.set(FIO.of(true)))
24-
: count
22+
e.fold(
23+
FIO.of(false),
24+
() => fiber.abort.and(await.set(FIO.of(true))),
25+
() =>
26+
count
2527
.update(_ => _ + 1)
2628
.and(
2729
count.read.chain(value =>
2830
value === 2 ? await.set(FIO.of(true)) : FIO.of(false)
2931
)
3032
)
33+
)
3134
)

src/internals/FiberContext.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import {ICancellable, IScheduler} from 'ts-scheduler'
66

7-
import {Exit} from '../main/Exit'
7+
import {Either} from '../main/Either'
88
import {Fiber} from '../main/Fiber'
99
import {FIO, UIO} from '../main/FIO'
1010
import {Instruction} from '../main/Instructions'
@@ -84,17 +84,15 @@ export class FiberContext<E = never, A = never> extends Fiber<E, A>
8484
return this
8585
}
8686

87-
public resumeAsync(cb: (exit: Exit<E, A>) => UIO<void>): UIO<void> {
88-
const eee = <X>(con: (x: X) => Exit<E, A>) => (data: X) => {
87+
public resumeAsync(cb: (exit: Either<E, A>) => UIO<void>): UIO<void> {
88+
const eee = <X>(con: (x: X) => Either<E, A>) => (data: X) => {
8989
// tslint:disable-next-line: no-use-before-declare
9090
const cancel = () => this.cancellationList.remove(id)
9191
const id = this.cancellationList.push(
9292
this.$fork(cb(con(data)).asInstruction).$resume(cancel, cancel)
9393
)
9494
}
9595

96-
return FIO.uio(
97-
() => void this.$resume(eee(Exit.failure), eee(Exit.success))
98-
)
96+
return FIO.uio(() => void this.$resume(eee(Either.left), eee(Either.right)))
9997
}
10098
}

src/internals/Id.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Simple Id function that takes in an input and returns the same value as it is.
3+
* @ignore
4+
*/
5+
export const Id = <A>(_: A): A => _

src/main/Await.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {mutable} from 'standard-data-structures'
22

33
import {CB} from '../internals/CB'
44

5-
import {Exit} from './Exit'
5+
import {Either} from './Either'
66
import {FIO, UIO} from './FIO'
77

88
/**
@@ -17,16 +17,10 @@ export class Await<E, A> {
1717
}
1818
private flag = false
1919
private readonly Q = mutable.DoublyLinkedList.of<[CB<E>, CB<A>]>()
20-
private result: Exit<E, A> = Exit.pending
20+
private result: Either<E, A> = Either.neither()
2121

2222
public get get(): FIO<E, A> {
23-
return this.getResult().chain(([status, result]) =>
24-
status === Exit.Success
25-
? FIO.of(result)
26-
: status === Exit.Failure
27-
? FIO.reject(result)
28-
: this.wait()
29-
) as FIO<E, A>
23+
return this.getResult().chain(e => e.fold(this.wait(), FIO.reject, FIO.of))
3024
}
3125

3226
public get isSet(): UIO<boolean> {
@@ -40,32 +34,28 @@ export class Await<E, A> {
4034
: this.setFlag(true)
4135
.and(
4236
io
43-
.chain(result => this.update(Exit.success(result)))
44-
.catch(err => this.update(Exit.failure(err)))
37+
.chain(result => this.update(Either.right(result)))
38+
.catch(err => this.update(Either.left(err)))
4539
)
4640
.const(true)
4741
)
4842
}
4943

50-
private getResult(): UIO<Exit<E, A>> {
44+
private getResult(): UIO<Either<E, A>> {
5145
return FIO.uio(() => this.result)
5246
}
5347

5448
private setFlag(value: boolean): UIO<void> {
5549
return FIO.uio(() => void (this.flag = value))
5650
}
5751

58-
private update(result: Exit<E, A>): UIO<void> {
52+
private update(result: Either<E, A>): UIO<void> {
5953
return FIO.uio(() => {
6054
this.result = result
6155

6256
while (this.Q.length > 0) {
6357
const cb = this.Q.shift() as [CB<E>, CB<A>]
64-
if (result[0] === Exit.Success) {
65-
cb[1](result[1])
66-
} else if (result[0] === Exit.Failure) {
67-
cb[0](result[1])
68-
}
58+
result.fold(undefined, ...cb)
6959
}
7060
})
7161
}

src/main/Either.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/* tslint:disable:prefer-function-over-method */
2+
3+
/**
4+
* Created by tushar on 07/09/19
5+
*/
6+
7+
export abstract class Either<L1, R1> {
8+
public static left<L>(left: L): Either<L, never> {
9+
return new Left(left)
10+
}
11+
public static neither(): Either<never, never> {
12+
return new Neither()
13+
}
14+
public static right<R>(right: R): Either<never, R> {
15+
return new Right(right)
16+
}
17+
18+
public abstract biChain<L2, R2>(
19+
LL: (l: L1) => Either<L2, R2>,
20+
RR: (r: R1) => Either<L2, R2>
21+
): Either<L2, R2>
22+
23+
public biMap<L2, R2>(LL: (l: L1) => L2, RR: (r: R1) => R2): Either<L2, R2> {
24+
return this.mapL(LL).mapR(RR)
25+
}
26+
27+
public chain<R2>(ab: (r: R1) => Either<L1, R2>): Either<L1, R2> {
28+
return this.chainR(ab)
29+
}
30+
public chainL<L2>(ab: (l: L1) => Either<L2, R1>): Either<L2, R1> {
31+
return this.biChain(ab, Either.right)
32+
}
33+
public chainR<R2>(ab: (r: R1) => Either<L1, R2>): Either<L1, R2> {
34+
return this.biChain(Either.left, ab)
35+
}
36+
37+
public abstract fold<S>(
38+
seed: S,
39+
LL: (l: L1, s: S) => S,
40+
RR: (r: R1, s: S) => S
41+
): S
42+
43+
public abstract getLeftOrElse(left: L1): L1
44+
public abstract getRightOrElse(right: R1): R1
45+
public map<R2>(ab: (r: R1) => R2): Either<L1, R2> {
46+
return this.mapR(ab)
47+
}
48+
public mapL<L2>(ab: (r: L1) => L2): Either<L2, R1> {
49+
return this.chainL(r => Either.left(ab(r)))
50+
}
51+
52+
public mapR<R2>(ab: (r: R1) => R2): Either<L1, R2> {
53+
return this.chainR(r => Either.right(ab(r)))
54+
}
55+
}
56+
57+
class Left<L1> extends Either<L1, never> {
58+
public readonly isLeft = true
59+
public readonly isNeither = false
60+
public readonly isRight = false
61+
62+
public constructor(public readonly left: L1) {
63+
super()
64+
}
65+
66+
public biChain<L2, R2>(
67+
LL: (l: L1) => Either<L2, R2>,
68+
RR: (r: never) => Either<L2, R2>
69+
): Either<L2, R2> {
70+
return LL(this.left)
71+
}
72+
73+
public fold<S>(S: S, LL: (l: L1, s: S) => S, RR: (r: never, s: S) => S): S {
74+
return LL(this.left, S)
75+
}
76+
77+
public getLeftOrElse(left: L1): L1 {
78+
return this.left
79+
}
80+
81+
public getRightOrElse(right: never): never {
82+
return right
83+
}
84+
}
85+
86+
class Right<R1> extends Either<never, R1> {
87+
public readonly isLeft = false
88+
public readonly isNeither = false
89+
public readonly isRight = true
90+
91+
public constructor(public readonly right: R1) {
92+
super()
93+
}
94+
95+
public biChain<L2, R2>(
96+
LL: (l: never) => Either<L2, R2>,
97+
RR: (r: R1) => Either<L2, R2>
98+
): Either<L2, R2> {
99+
return RR(this.right)
100+
}
101+
public fold<S>(S: S, LL: (l: never, s: S) => S, RR: (r: R1, s: S) => S): S {
102+
return RR(this.right, S)
103+
}
104+
105+
public getLeftOrElse(left: never): never {
106+
return left
107+
}
108+
public getRightOrElse(right: R1): R1 {
109+
return this.right
110+
}
111+
}
112+
113+
class Neither extends Either<never, never> {
114+
public readonly isLeft = false
115+
public readonly isNeither = true
116+
public readonly isRight = false
117+
118+
public biChain<L2, R2>(
119+
LL: (l: never) => Either<L2, R2>,
120+
RR: (r: never) => Either<L2, R2>
121+
): Either<L2, R2> {
122+
return this
123+
}
124+
125+
public fold<S>(
126+
S: S,
127+
LL: (l: never, s: S) => S,
128+
RR: (r: never, s: S) => S
129+
): S {
130+
return S
131+
}
132+
133+
public getLeftOrElse(left: never): never {
134+
return left
135+
}
136+
137+
public getRightOrElse(right: never): never {
138+
return right
139+
}
140+
}

src/main/Exit.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main/FIO.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@ import {ICancellable, IScheduler} from 'ts-scheduler'
88

99
import {CB} from '../internals/CB'
1010
import {coordinate} from '../internals/Coordinate'
11+
import {Id} from '../internals/Id'
1112
import {IRuntime} from '../runtimes/IRuntime'
1213

1314
import {Await} from './Await'
14-
import {Exit} from './Exit'
15+
import {Either} from './Either'
1516
import {Fiber} from './Fiber'
1617
import {Instruction, Tag} from './Instructions'
1718
import {Ref} from './Ref'
1819

19-
const Id = <A>(_: A): A => _
20-
const ExitRef = <E = never, A = never>() => Ref.of<Exit<E, A>>(Exit.pending)
20+
const ExitRef = <E = never, A = never>() =>
21+
Ref.of<Either<E, A>>(Either.neither())
2122

2223
export type NoEnv = unknown
2324

@@ -224,14 +225,10 @@ export class FIO<E1 = unknown, A1 = unknown, R1 = NoEnv> {
224225
}
225226

226227
/**
227-
* Creates an IO from [[Exit]]
228+
* Creates an IO from [[Either]]
228229
*/
229-
public static fromExit<E, A>(exit: Exit<E, A>): FIO<E, A> {
230-
return Exit.isSuccess(exit)
231-
? FIO.of(exit[1])
232-
: Exit.isFailure(exit)
233-
? FIO.reject(exit[1])
234-
: FIO.never()
230+
public static fromExit<E, A>(exit: Either<E, A>): IO<E, A> {
231+
return exit.fold<IO<E, A>>(FIO.never(), FIO.reject, FIO.of)
235232
}
236233

237234
/**
@@ -541,8 +538,8 @@ export class FIO<E1 = unknown, A1 = unknown, R1 = NoEnv> {
541538
*/
542539
public raceWith<E2, A2, R2>(
543540
that: FIO<E2, A2, R2>,
544-
cb1: (exit: Exit<E1, A1>, fiber: Fiber<E2, A2>) => UIO<void>,
545-
cb2: (exit: Exit<E2, A2>, fiber: Fiber<E1, A1>) => UIO<void>
541+
cb1: (exit: Either<E1, A1>, fiber: Fiber<E2, A2>) => UIO<void>,
542+
cb2: (exit: Either<E2, A2>, fiber: Fiber<E1, A1>) => UIO<void>
546543
): FIO<never, void, R1 & R2> {
547544
return this.fork.zip(that.fork).chain(({0: f1, 1: f2}) => {
548545
const resume1 = f1.resumeAsync(exit => cb1(exit, f2))
@@ -553,10 +550,10 @@ export class FIO<E1 = unknown, A1 = unknown, R1 = NoEnv> {
553550
}
554551

555552
/**
556-
* Runs the [[FIO]] instance asynchronously and calls the callback passed with an [[Exit]] object.
553+
* Runs the [[FIO]] instance asynchronously and calls the callback passed with an [[Either]] object.
557554
*/
558555
public resumeAsync(
559-
cb: (exit: Exit<E1, A1>) => UIO<void>
556+
cb: (exit: Either<E1, A1>) => UIO<void>
560557
): FIO<never, void, R1> {
561558
return this.fork.chain(_ => _.resumeAsync(cb))
562559
}

src/main/Fiber.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {ICancellable} from 'ts-scheduler'
22

33
import {FIO, UIO} from '../main/FIO'
44

5-
import {Exit} from './Exit'
5+
import {Either} from './Either'
66

77
/**
88
* Fibers are data structures that provide you a handle to control the execution of its `IO`.
@@ -24,5 +24,5 @@ export abstract class Fiber<E, A> implements ICancellable {
2424
public cancel(): void {
2525
this.$abort()
2626
}
27-
public abstract resumeAsync(cb: (exit: Exit<E, A>) => UIO<void>): UIO<void>
27+
public abstract resumeAsync(cb: (exit: Either<E, A>) => UIO<void>): UIO<void>
2828
}

0 commit comments

Comments
 (0)