Skip to content

Commit

Permalink
feat: add maybe map
Browse files Browse the repository at this point in the history
  • Loading branch information
bonjourmauko committed Aug 17, 2024
1 parent adc2604 commit d37f185
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export type { PostalAddress } from '~/stores/PostalAddressStore'
export type { GeoCoordinates } from '~/stores/GeoCoordinatesStore'
export type { IsString } from '~/utils/types/string'
export type { IsNumber } from '~/utils/types/number'
export type { Map } from '~/utils/typeclass/functor'
20 changes: 20 additions & 0 deletions src/utils/adt/maybe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,23 @@ export const match: Match = (onNothing, onJust) => (x) =>
.with({ _tag: 'Nothing' }, onNothing)
.with({ _tag: 'Just' }, ({ value }) => onJust(value))
.exhaustive()

/**
* Maybe functor to wrap/unwrap a function.
*
* @param {Function} f The mapping function that transforms the input value.
* @returns {Function} A new function that takes a `Maybe` container and applies
* the mapping function to its value.
*/
export type Map = <A, B>(f: (x: A) => B) => (Fx: Maybe<A>) => Maybe<B>

/**
* Maybe functor to wrap/unwrap a function.
*
* @todo Add support for curried functions.
*/
export const map: Map = (f) =>
match(
() => nothing,
(a) => just(f(a))
)
2 changes: 2 additions & 0 deletions src/utils/typeclass/functor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
*
* @module functor
*/

export type { Map } from '~/utils/adt/maybe'
22 changes: 21 additions & 1 deletion test/unit/utils/adt/maybe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Matcher } from '~/utils/adt/maybe'

import { describe, expect, expectTypeOf, test } from 'vitest'

import { isJust, isNothing, just, match, nothing } from '~/utils/adt/maybe'
import { isJust, isNothing, just, map, match, nothing } from '~/utils/adt/maybe'

describe('Maybe', () => {
describe('Given a value or the absence thereof', () => {
Expand Down Expand Up @@ -98,3 +98,23 @@ describe('match/2', () => {
})
})
})

describe('map/1', () => {
describe('Given a function', () => {
type Inc<A> = (a: A) => A
const inc: Inc<number> = (a) => a + 1

type MaybeAdd<A> = (a: Maybe<A>) => Maybe<A>
const maybeAdd: MaybeAdd<number> = map(inc)

test('When lifting it with "just"', () => {
const result = maybeAdd(just(1))
expect(result).toStrictEqual(just(2))
})

test('When lifting it with "nothing"', () => {
const result = maybeAdd(nothing)
expect(result).toBe(nothing)
})
})
})

0 comments on commit d37f185

Please sign in to comment.