Skip to content

Commit

Permalink
refactor(either): rename Exit to Either
Browse files Browse the repository at this point in the history
Either need not be internal to this project.

BREAKING CHANGE: `Exit` is renamed to `Either`
  • Loading branch information
tusharmath committed Sep 7, 2019
1 parent 6c4aab6 commit f2f5034
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 94 deletions.
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* tslint:disable:file-name-casing */
export {Await} from './src/main/Await'
export {Exit} from './src/main/Exit'
export {Either} from './src/main/Either'
export {Fiber} from './src/main/Fiber'
export {FIO, IO, Task, TaskR, UIO} from './src/main/FIO'
export {FStream, Stream} from './src/main/FStream'
Expand Down
15 changes: 9 additions & 6 deletions src/internals/Coordinate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Await} from '../main/Await'
import {Exit} from '../main/Exit'
import {Either} from '../main/Either'
import {Fiber} from '../main/Fiber'
import {FIO, UIO} from '../main/FIO'
import {Ref} from '../main/Ref'
Expand All @@ -10,22 +10,25 @@ import {Ref} from '../main/Ref'
* @ignore
*/
export const coordinate = <E1, A1, E2, A2>(
exit: Exit<E1, A1>,
exit: Either<E1, A1>,
fiber: Fiber<E2, A2>,
ref: Ref<Exit<E1, A1>>,
ref: Ref<Either<E1, A1>>,
count: Ref<number>,
await: Await<never, boolean>
): UIO<boolean> =>
ref
.set(exit)
.chain(e =>
Exit.isFailure(e)
? fiber.abort.and(await.set(FIO.of(true)))
: count
e.fold(
FIO.of(false),
() => fiber.abort.and(await.set(FIO.of(true))),
() =>
count
.update(_ => _ + 1)
.and(
count.read.chain(value =>
value === 2 ? await.set(FIO.of(true)) : FIO.of(false)
)
)
)
)
10 changes: 4 additions & 6 deletions src/internals/FiberContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

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

import {Exit} from '../main/Exit'
import {Either} from '../main/Either'
import {Fiber} from '../main/Fiber'
import {FIO, UIO} from '../main/FIO'
import {Instruction} from '../main/Instructions'
Expand Down Expand Up @@ -84,17 +84,15 @@ export class FiberContext<E = never, A = never> extends Fiber<E, A>
return this
}

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

return FIO.uio(
() => void this.$resume(eee(Exit.failure), eee(Exit.success))
)
return FIO.uio(() => void this.$resume(eee(Either.left), eee(Either.right)))
}
}
5 changes: 5 additions & 0 deletions src/internals/Id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Simple Id function that takes in an input and returns the same value as it is.
* @ignore
*/
export const Id = <A>(_: A): A => _
26 changes: 8 additions & 18 deletions src/main/Await.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {mutable} from 'standard-data-structures'

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

import {Exit} from './Exit'
import {Either} from './Either'
import {FIO, UIO} from './FIO'

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

public get get(): FIO<E, A> {
return this.getResult().chain(([status, result]) =>
status === Exit.Success
? FIO.of(result)
: status === Exit.Failure
? FIO.reject(result)
: this.wait()
) as FIO<E, A>
return this.getResult().chain(e => e.fold(this.wait(), FIO.reject, FIO.of))
}

public get isSet(): UIO<boolean> {
Expand All @@ -40,32 +34,28 @@ export class Await<E, A> {
: this.setFlag(true)
.and(
io
.chain(result => this.update(Exit.success(result)))
.catch(err => this.update(Exit.failure(err)))
.chain(result => this.update(Either.right(result)))
.catch(err => this.update(Either.left(err)))
)
.const(true)
)
}

private getResult(): UIO<Exit<E, A>> {
private getResult(): UIO<Either<E, A>> {
return FIO.uio(() => this.result)
}

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

private update(result: Exit<E, A>): UIO<void> {
private update(result: Either<E, A>): UIO<void> {
return FIO.uio(() => {
this.result = result

while (this.Q.length > 0) {
const cb = this.Q.shift() as [CB<E>, CB<A>]
if (result[0] === Exit.Success) {
cb[1](result[1])
} else if (result[0] === Exit.Failure) {
cb[0](result[1])
}
result.fold(undefined, ...cb)
}
})
}
Expand Down
140 changes: 140 additions & 0 deletions src/main/Either.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* tslint:disable:prefer-function-over-method */

/**
* Created by tushar on 07/09/19
*/

export abstract class Either<L1, R1> {
public static left<L>(left: L): Either<L, never> {
return new Left(left)
}
public static neither(): Either<never, never> {
return new Neither()
}
public static right<R>(right: R): Either<never, R> {
return new Right(right)
}

public abstract biChain<L2, R2>(
LL: (l: L1) => Either<L2, R2>,
RR: (r: R1) => Either<L2, R2>
): Either<L2, R2>

public biMap<L2, R2>(LL: (l: L1) => L2, RR: (r: R1) => R2): Either<L2, R2> {
return this.mapL(LL).mapR(RR)
}

public chain<R2>(ab: (r: R1) => Either<L1, R2>): Either<L1, R2> {
return this.chainR(ab)
}
public chainL<L2>(ab: (l: L1) => Either<L2, R1>): Either<L2, R1> {
return this.biChain(ab, Either.right)
}
public chainR<R2>(ab: (r: R1) => Either<L1, R2>): Either<L1, R2> {
return this.biChain(Either.left, ab)
}

public abstract fold<S>(
seed: S,
LL: (l: L1, s: S) => S,
RR: (r: R1, s: S) => S
): S

public abstract getLeftOrElse(left: L1): L1
public abstract getRightOrElse(right: R1): R1
public map<R2>(ab: (r: R1) => R2): Either<L1, R2> {
return this.mapR(ab)
}
public mapL<L2>(ab: (r: L1) => L2): Either<L2, R1> {
return this.chainL(r => Either.left(ab(r)))
}

public mapR<R2>(ab: (r: R1) => R2): Either<L1, R2> {
return this.chainR(r => Either.right(ab(r)))
}
}

class Left<L1> extends Either<L1, never> {
public readonly isLeft = true
public readonly isNeither = false
public readonly isRight = false

public constructor(public readonly left: L1) {
super()
}

public biChain<L2, R2>(
LL: (l: L1) => Either<L2, R2>,
RR: (r: never) => Either<L2, R2>
): Either<L2, R2> {
return LL(this.left)
}

public fold<S>(S: S, LL: (l: L1, s: S) => S, RR: (r: never, s: S) => S): S {
return LL(this.left, S)
}

public getLeftOrElse(left: L1): L1 {
return this.left
}

public getRightOrElse(right: never): never {
return right
}
}

class Right<R1> extends Either<never, R1> {
public readonly isLeft = false
public readonly isNeither = false
public readonly isRight = true

public constructor(public readonly right: R1) {
super()
}

public biChain<L2, R2>(
LL: (l: never) => Either<L2, R2>,
RR: (r: R1) => Either<L2, R2>
): Either<L2, R2> {
return RR(this.right)
}
public fold<S>(S: S, LL: (l: never, s: S) => S, RR: (r: R1, s: S) => S): S {
return RR(this.right, S)
}

public getLeftOrElse(left: never): never {
return left
}
public getRightOrElse(right: R1): R1 {
return this.right
}
}

class Neither extends Either<never, never> {
public readonly isLeft = false
public readonly isNeither = true
public readonly isRight = false

public biChain<L2, R2>(
LL: (l: never) => Either<L2, R2>,
RR: (r: never) => Either<L2, R2>
): Either<L2, R2> {
return this
}

public fold<S>(
S: S,
LL: (l: never, s: S) => S,
RR: (r: never, s: S) => S
): S {
return S
}

public getLeftOrElse(left: never): never {
return left
}

public getRightOrElse(right: never): never {
return right
}
}
28 changes: 0 additions & 28 deletions src/main/Exit.ts

This file was deleted.

25 changes: 11 additions & 14 deletions src/main/FIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import {ICancellable, IScheduler} from 'ts-scheduler'

import {CB} from '../internals/CB'
import {coordinate} from '../internals/Coordinate'
import {Id} from '../internals/Id'
import {IRuntime} from '../runtimes/IRuntime'

import {Await} from './Await'
import {Exit} from './Exit'
import {Either} from './Either'
import {Fiber} from './Fiber'
import {Instruction, Tag} from './Instructions'
import {Ref} from './Ref'

const Id = <A>(_: A): A => _
const ExitRef = <E = never, A = never>() => Ref.of<Exit<E, A>>(Exit.pending)
const ExitRef = <E = never, A = never>() =>
Ref.of<Either<E, A>>(Either.neither())

export type NoEnv = unknown

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

/**
* Creates an IO from [[Exit]]
* Creates an IO from [[Either]]
*/
public static fromExit<E, A>(exit: Exit<E, A>): FIO<E, A> {
return Exit.isSuccess(exit)
? FIO.of(exit[1])
: Exit.isFailure(exit)
? FIO.reject(exit[1])
: FIO.never()
public static fromExit<E, A>(exit: Either<E, A>): IO<E, A> {
return exit.fold<IO<E, A>>(FIO.never(), FIO.reject, FIO.of)
}

/**
Expand Down Expand Up @@ -541,8 +538,8 @@ export class FIO<E1 = unknown, A1 = unknown, R1 = NoEnv> {
*/
public raceWith<E2, A2, R2>(
that: FIO<E2, A2, R2>,
cb1: (exit: Exit<E1, A1>, fiber: Fiber<E2, A2>) => UIO<void>,
cb2: (exit: Exit<E2, A2>, fiber: Fiber<E1, A1>) => UIO<void>
cb1: (exit: Either<E1, A1>, fiber: Fiber<E2, A2>) => UIO<void>,
cb2: (exit: Either<E2, A2>, fiber: Fiber<E1, A1>) => UIO<void>
): FIO<never, void, R1 & R2> {
return this.fork.zip(that.fork).chain(({0: f1, 1: f2}) => {
const resume1 = f1.resumeAsync(exit => cb1(exit, f2))
Expand All @@ -553,10 +550,10 @@ export class FIO<E1 = unknown, A1 = unknown, R1 = NoEnv> {
}

/**
* Runs the [[FIO]] instance asynchronously and calls the callback passed with an [[Exit]] object.
* Runs the [[FIO]] instance asynchronously and calls the callback passed with an [[Either]] object.
*/
public resumeAsync(
cb: (exit: Exit<E1, A1>) => UIO<void>
cb: (exit: Either<E1, A1>) => UIO<void>
): FIO<never, void, R1> {
return this.fork.chain(_ => _.resumeAsync(cb))
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/Fiber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {ICancellable} from 'ts-scheduler'

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

import {Exit} from './Exit'
import {Either} from './Either'

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

0 comments on commit f2f5034

Please sign in to comment.