Skip to content

Commit

Permalink
export tag; renaming functions
Browse files Browse the repository at this point in the history
renaming `flatten_enum` to `extract_variant` and `flatten_enum_old` to `flatten_enum`
  • Loading branch information
steinerkelvin committed Aug 1, 2022
1 parent ec44f27 commit 0517de0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 39 deletions.
18 changes: 10 additions & 8 deletions src/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ export type Variant<Tag extends Key, T> = { [x in Tag]: T }
export type TagVariants<T> = { [K in keyof T]: Variant<K, T[K]> }
export type Enum<T> = TagVariants<T>[keyof T]

export type FlatVariant<Tag extends Key, T> = { $: Tag; val: T }
export type FlatEnum<T> = { [K in keyof T]: FlatVariant<K, T[K]> }[keyof T]
export type ExtractVariant<Tag extends Key, T> = { $: Tag; val: T }
export type ExtractVariants<T> = {
[K in keyof T]: ExtractVariant<K, T[K]>
}[keyof T]

export type VariantsFrom<T> = AllFields<T>
export type FlatEnumFrom<T> = FlatEnum<VariantsFrom<T>>
export type FlatEnumFrom<T> = ExtractVariants<VariantsFrom<T>>

export type FlatVariantOld<Tag extends Key, T> = { $: Tag } & T
export type FlatEnumOld<T> = {
[K in keyof T]: FlatVariantOld<K, T[K]>
export type FlatVariant<Tag extends Key, T> = { $: Tag } & T
export type FlatEnum<T> = {
[K in keyof T]: FlatVariant<K, T[K]>
}[keyof T]

export function flatten_enum_old<V>(value: Enum<V>): FlatEnumOld<V> {
export function flatten_enum<V>(value: Enum<V>): FlatEnum<V> {
for (let key in value) {
// TODO: use Object.keys
if (key !== "$") {
Expand All @@ -29,7 +31,7 @@ export function flatten_enum_old<V>(value: Enum<V>): FlatEnumOld<V> {
throw new Error(`Variant is empty: '${value}'.`)
}

export function flatten_enum<E>(value: E): FlatEnumFrom<E> {
export function extract_variant<E>(value: E): FlatEnumFrom<E> {
for (let key in value) {
// TODO: use Object.keys
let _result = value[key]
Expand Down
51 changes: 28 additions & 23 deletions src/example.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { Enum } from "."
import { flatten_enum, flatten_enum_f, match, if_let } from "."
import {
extract_variant,
extract_variant_f,
match,
if_let,
} from "."

type Stuff = Enum<{
Color: Color
Expand All @@ -20,11 +25,26 @@ function example() {
const a: Stuff = { Color: { r: 10, g: 20, b: 35 } }
const b: Stuff = { BW: { value: true } }

const all: Stuff[] = [a, b]
const items: Stuff[] = [a, b]

for (const _elem of all) {
console.log(`Matching with flatten_enum...`)
const variant = flatten_enum(_elem)
console.log(`Matching with 'match'...`)
for (const elem of items) {
match(elem)({
Color: (color) => console.log(color.r + color.g + color.b),
BW: (bw) => console.log(bw.value),
})
}

console.log(`Matching with 'if_let'...`)
for (const elem of items) {
if_let(elem)("Color")((color) =>
console.log(`This is color: R:${color.r} G:${color.g} B:${color.b}`)
)(() => console.log(`This is not color: ${elem}`))
}

console.log(`Matching with 'extract_variant'...`)
for (const _elem of items) {
const variant = extract_variant(_elem)
switch (variant.$) {
case "Color":
const color = variant.val
Expand All @@ -39,9 +59,9 @@ function example() {
}
}

for (const elem of all) {
console.log(`Matching with flatten_enum_f...`)
flatten_enum_f(elem)(({ $, val }) => {
console.log(`Matching with 'extract_variant_f'...`)
for (const elem of items) {
extract_variant_f(elem)(({ $, val }) => {
switch ($) {
case "Color":
console.log(`R: ${val.r}, G: ${val.b} + B: ${val.g}`)
Expand All @@ -54,21 +74,6 @@ function example() {
}
})
}

for (const elem of all) {
console.log(`Matching with map_enum...`)
match(elem)({
Color: (color) => console.log(color.r + color.g + color.b),
BW: (bw) => console.log(bw.value),
})
}

for (const elem of all) {
console.log(`Matching with if_let...`)
if_let(elem)("Color")((color) =>
console.log(`This is color: R:${color.r} G:${color.g} B:${color.b}`)
)(() => console.log(`This is not color: ${elem}`))
}
}

example()
14 changes: 8 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import type { FlatEnumFrom, VariantsFrom } from "./enum"
import { flatten_enum } from "./enum"
import { extract_variant } from "./enum"

export type { Enum } from "./enum"
export { flatten_enum } from "./enum"
export { extract_variant, flatten_enum } from "./enum"

export { Tag, Tagged } from './tag'

export type Option<T> = T | null

export const flatten_enum_f =
export const extract_variant_f =
<N>(value: N) =>
<R>(f: (v: FlatEnumFrom<N>) => R) =>
f(flatten_enum(value))
f(extract_variant(value))

type MatchDict<V, R = void> = { [tag in keyof V]: (v: V[tag]) => R }

export const match =
<N>(value: N) =>
<R>(matcher: MatchDict<VariantsFrom<N>, R>): R =>
flatten_enum_f(value)(({ $, val }) => {
extract_variant_f(value)(({ $, val }) => {
let arm = matcher[$]
return arm(val)
})
Expand All @@ -26,4 +28,4 @@ export const if_let =
<K extends keyof VariantsFrom<N>>(tag: K) =>
<R>(th: (v: VariantsFrom<N>[K]) => R) =>
(el: () => R): R =>
flatten_enum_f(value)(({ $, val }) => ($ === tag ? th(val) : el()))
extract_variant_f(value)(({ $, val }) => ($ === tag ? th(val) : el()))
4 changes: 2 additions & 2 deletions src/tag.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
declare const TAG: unique symbol
export type Tag<T> = { readonly [TAG]: T }
declare const TAG_KEY: unique symbol
export type Tag<T> = { readonly [TAG_KEY]: T }

export type Tagged<T, V> = Tag<T> & V

0 comments on commit 0517de0

Please sign in to comment.