Skip to content

Commit

Permalink
Added map
Browse files Browse the repository at this point in the history
  • Loading branch information
mantoci committed Sep 29, 2023
1 parent 6776ba2 commit 60f79c2
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 34 deletions.
13 changes: 6 additions & 7 deletions examples/tennis-game/tennis-game.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { just, maybe, nothing } from '../../src'
import { Maybe, right } from '../../src'
import { just, maybe, Maybe, nothing } from '../../src'

type Player = {
name: string
Expand All @@ -14,7 +13,7 @@ const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)

const getAllScoreText = (player: Player) =>
maybe(SCORES[player.scoreIndex])
.flatMap((it) => right(capitalize(it)))
.map(capitalize)
.getOrElse(() => '')

const createPlayer = (name: string): Player => ({
Expand Down Expand Up @@ -56,16 +55,16 @@ export const createGame = (firstPlayerName: string, secondPlayerName: string): T

const handleDraw = (): MaybeScore =>
isDeuce()
.flatMap(() => right('Deuce'))
.mapLeft(() => isAll().flatMap(() => right(`${getAllScoreText(playerOne)} all`)))
.map(() => 'Deuce')
.mapLeft(() => isAll().map(() => `${getAllScoreText(playerOne)} all`))

const handleAdvantage = (): MaybeScore => {
const rank = getRank()
const spread = Math.abs(rank)
const topPlayer = rank > 0 ? playerOne : playerTwo
return allCanWin()
.flatMap(() => (spread === 1 ? just(`Advantage ${topPlayer.name}`) : nothing<string>()))
.mapLeft(() => (canWin(topPlayer) && spread >= 2 ? just(`${topPlayer.name} wins`) : nothing<string>()))
.flatMap(() => (spread === 1 ? just(`Advantage ${topPlayer.name}`) : nothing()))
.mapLeft(() => (canWin(topPlayer) && spread >= 2 ? just(`${topPlayer.name} wins`) : nothing()))
}

return {
Expand Down
44 changes: 25 additions & 19 deletions src/either/either.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Either, Left, Right } from '../types'
import { Either } from '../types'
import { createSerializable } from './serializer'

const PROTOTYPE = {}
Expand All @@ -13,38 +13,44 @@ export const isEither = <E, A>(input: unknown): input is Either<E, A> => {

const seal = <T>(adt: T): T => Object.freeze(Object.assign(Object.create(PROTOTYPE), adt))

const createRight = <E, A>(data: A) =>
seal<Right<E, A>>({
const createRight = <E, A>(data: A) => {
const equals = (operand: Either<E, A>) =>
operand.fold(
() => false,
(it) => it === data
)
const map = <B>(ifRight: (right: A) => B) => rightOf<E, any>(ifRight(data))
const fold = <B>(_: (left: E) => B, ifRight: (right: A) => B) => ifRight(data)
return seal<Either<E, A>>({
...createSerializable('Right', data),
isLeft: false,
isRight: true,
equals: (operand) =>
operand.fold(
() => false,
(it) => it === data
),
fold: <B>(_: (left: E) => B, ifRight: (right: A) => B) => ifRight(data),
equals: equals,
fold,
getOrElse: () => data,
// map: (ifRight) => rightOf<E, any>(ifRight(data)),
flatMap: (ifRight) => rightOf<E, any>(ifRight(data)),
map,
flatMap: map,
mapLeft: () => rightOf(data),
})
}

const createLeft = <E, A>(data: E) => {
const equals = (operand: Either<E, A>) =>
operand.fold(
(it) => it === data,
() => false
)
const map = <B>() => leftOf<E, B>(data)
const fold = <B>(ifLeft: (value: E) => B) => ifLeft(data)
return seal<Left<E, A>>({
return seal<Either<E, A>>({
...createSerializable('Left', data),
isLeft: true,
isRight: false,
equals: (operand) =>
operand.fold(
(it) => it === data,
() => false
),
equals: equals,
fold,
getOrElse: fold,
// map: () => leftOf(data),
flatMap: () => leftOf(data),
map: map,
flatMap: map,
mapLeft: (ifLeft) => leftOf<any, A>(ifLeft(data)),
})
}
Expand Down
8 changes: 4 additions & 4 deletions src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { maybe } from './maybe/maybe'
describe('Integration', () => {
it('can be chained', () => {
const actual: string = right<string, number>(0)
.flatMap((it) => right(it + 10))
.flatMap((it) => right(it * 2))
.map((it) => it + 10)
.map((it) => it * 2)
.flatMap((it) => (it === 20 ? left('yessss') : right(it)))
.mapLeft(() => right(100))
.flatMap((it) => right(it === 100 ? 'happy' : 'very sad'))
.map((it) => (it === 100 ? 'happy' : 'very sad'))
.fold(
() => 'very sad',
() => 'very very sad',
(it) => it
)

Expand Down
8 changes: 4 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ interface EQ<E, A> {
equals(value: Either<E, A>): boolean
}

// type AnyNonEither = Exclude<any, Either<any, any>>
type Scalar<T> = Exclude<T, Either<any, any>>

interface Chainable<E, A> {
// map<B extends AnyNonEither = A>(ifRight: (right: A) => B): Either<E, B>
map<B>(ifRight: (right: A) => Scalar<A | B>): Either<E, B>

flatMap<B = A>(ifRight: (right: A) => Left<E, A> | Right<E, B>): Either<E, B>
flatMap<B>(ifRight: (right: A) => Either<E, A | B>): Either<E, B>

mapLeft<G = E>(ifLeft: (left: E) => Left<G, A> | Right<E, A>): Either<G, A>
mapLeft<G>(ifLeft: (left: E) => Either<G | E, A>): Either<G, A>
}

interface Foldable<E, A> {
Expand Down

0 comments on commit 60f79c2

Please sign in to comment.