Skip to content

Instantly share code, notes, and snippets.

View WimJongeneel's full-sized avatar
:octocat:

Wim Jongeneel WimJongeneel

:octocat:
View GitHub Profile
export const match = <a, b>(value: a) => builder<a, b>(value)(() => undefined, [])
const builder = <a, b>(
value: a
) => (
otherwise: () => b = () => null,
patterns: Array<[Pattern<a>, Fun<a, b>]> = []
) => ({
with: (pattern: a, expr: fun<a, b>) =>
builder(value)(otherwise, [...patterns, [pattern, expr]]),
@WimJongeneel
WimJongeneel / match.1.ts
Created December 15, 2019 10:46
match-1.ts
match(1)
.with(1, v => v * 2)
.with(2, v => v * v)
.otherwise(() => -1)
.run()
let vector = { x: 1, y: 1 }
if(vector.z != undefined) return 'vector3'
if(vector.y != undefined) return 'vector2'
return 'vector1'
match(vector)
.with({ x: 1, y: 1, z: 1 }, () => 'vector3')
.with({ x: 2, y:1 }, () => 'vector2')
.with({ x: 1 }, () => 'vector1')
.otherwise( () => 'no match')
.run()
type Pattern<a> = { [ k in keyof a ]?: Pattern<a[k]> }
const match_pattern = <a>(value: a, pattern: Pattern<a>) => typeof(value) != 'object'
? value === pattern
: Object.keys(pattern).every(k => pattern[k] == undefined ? false : match_pattern(value[k], pattern[k]))
type Option<a> = { kind: 'none' } | { kind: 'some', value: a }
let val: Option<string> = { kind: 'some', value: 'hello' }
// Conditinal way of geting the value
if(val.kind == 'some') return val.value
// Pattern matching way of geting the value
match(val)
.with({ kind: 'some' }, o => o.value) // TypeError!
with: <p extends Pattern<a>>(
pattern: p,
expr: (a: Extract<a, typeof pattern>) => b
) => match(value, otherwise, [...patterns, [pattern, expr]])
type LeastUpperBound<a, b> = b extends a ? b : a extends b ? a : never
interface Blog { id: number, title: string }
// Will be { id: number, title: string } | { errorMessage: string }
let httpResult: any = /* API logic. */
let result = httpResult.errorMesage
? new Error(httpResult.errorMessage)
: ({ id: httpResult.Id, title: httpResult.Title })
match<any, Blog | Error>(httpResult)
.with({Id: Number, Title: String }, r => ({id: r.Id, title: r.Title}))
.with({errorMessage: String}, r => new Error(r.errorMessage))
.otherwise(() => new Error('Client parse error'))
.run()