Skip to content

Instantly share code, notes, and snippets.

@waynevanson
Created April 12, 2020 10:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save waynevanson/ea221c585fce9a535bfd8f1397f2a921 to your computer and use it in GitHub Desktop.
Save waynevanson/ea221c585fce9a535bfd8f1397f2a921 to your computer and use it in GitHub Desktop.
A port of switch-case statements for fp-ts.
/**
* A port of switch-case statements for fp-ts.
*
* This could be broken down further and perhaps extended into a new type-class.
* It does the specific job I needed it to.
*
* If you have an abstraction that might help, i'd love to hear about it!
*/
import { array, either, option } from "fp-ts";
import { Predicate, Refinement } from "fp-ts/lib/function";
import { NonEmptyArray } from "fp-ts/lib/NonEmptyArray";
import { pipe } from "fp-ts/lib/pipeable";
import { Either } from "fp-ts/lib/Either";
import { Option } from "fp-ts/lib/Option";
/**
* A function to test the initial value against.
*/
export type Pattern<A, B extends A> = Predicate<A> | Refinement<A, B>;
/**
* A function to call when the `pattern` returns true.
*/
export type Statement<E, A> = (ffa: A) => E;
/**
* A tuple of pattern-function pairs.
*/
export type Case<E, A, B extends A> = [Pattern<A, B>, Statement<E, A>];
/**
* A switch-case statement for the functionally inclined.
*
* For any `pattern` returning true, it's `statement` will be called.
*/
export const match = <E, A, B extends A = never>(
initial: A,
cases: NonEmptyArray<Case<E, A, B>>
): Either<E[], Option<E>> =>
pipe(
cases,
array.map(([pattern, ffa]) =>
pipe(initial, option.fromPredicate(pattern), option.map(ffa))
),
array.compact,
// I believe this portion could be broken down into sub-functions.
array.foldLeft(
// if length === 0, default case
() => either.right(option.none),
(head, tail) =>
array.isEmpty(tail)
? // if length === 1, some
either.right(option.some(head))
: // if length > 1, error
either.left(tail)
)
);
@dlip-immutable
Copy link

I came up with another way:

const switchCase = <T extends string | number | symbol, U>(value: T, cases: Record<T, Lazy<U>>, def: Lazy<U>) =>
    value in cases ? cases[value]() : def();

@florianbepunkt
Copy link

Could you please add a usage example?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment