Skip to content

Instantly share code, notes, and snippets.

@unclechu
Last active July 13, 2023 06:47
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save unclechu/eb37cc81e80afbbb5e74990b62ea21f6 to your computer and use it in GitHub Desktop.
Save unclechu/eb37cc81e80afbbb5e74990b62ea21f6 to your computer and use it in GitHub Desktop.
Nim: algebraic data types (Maybe and Either), kinda Eq typeclass instances, kinda functors
type
MaybeKind = enum Just, Nothing
Maybe[T] = object
case kind: MaybeKind
of Just: value: T
of Nothing: discard
EitherKind = enum Left, Right
Either[L, R] = object
case kind: EitherKind
of Left: left: L
of Right: right: R
let
a = Maybe[int32](kind: Nothing)
b = Maybe[int32](kind: Just, value: 9000)
c = Maybe[int32](kind: Just, value: 9000)
d = Maybe[int32](kind: Just, value: 100)
e = Maybe[int32](kind: Nothing)
aa = Maybe[uint16](kind: Nothing)
ab = Maybe[uint16](kind: Nothing)
ac = Maybe[uint16](kind: Just, value: 10)
ad = Maybe[uint16](kind: Just, value: 10)
ae = Maybe[uint16](kind: Just, value: 20)
ba = Either[uint, bool](kind: Left, left: 5)
bb = Either[uint, bool](kind: Left, left: 5)
bc = Either[uint, bool](kind: Right, right: true)
bd = Either[uint, bool](kind: Right, right: true)
be = Either[uint, bool](kind: Right, right: false)
bf = Either[uint, bool](kind: Left, left: 6)
proc `==`[T](a: Maybe[T], b: Maybe[T]): bool =
case a.kind
of Nothing: b.kind == Nothing
of Just: b.kind == Just and a.value == b.value
proc `==`[L, R](a: Either[L, R], b: Either[L, R]): bool =
case a.kind
of Left: b.kind == Left and a.left == b.left
of Right: b.kind == Right and a.right == b.right
proc `<$>`[A, B](f: (proc (x: A): B); a: Maybe[A]): Maybe[B] =
case a.kind
of Just: Maybe[B](kind: Just, value: a.value.f)
of Nothing: Maybe[B](kind: Nothing)
proc `<$>`[L, R, N](f: (proc (x: R): N); a: Either[L, R]): Either[L, N] =
case a.kind
of Right: Either[L, N](kind: Right, right: a.right.f)
of Left: Either[L, N](kind: Left, left: a.left)
assert(a == e)
assert(b == c)
assert(b != d)
assert(c != d)
assert(a != b)
assert(b != e)
assert(aa == ab)
assert(ab != ac)
assert(ac == ad)
assert(ad != ae)
assert(ac != ae)
assert(ba == bb)
assert(bb != bc)
assert(bc == bd)
assert(bd != be)
assert(be != bf)
assert(ba != bf)
proc divBy2(x: int32): int32 = x div 2
proc divBy2x(x: int32): int16 = int16 x div 2
let b2: Maybe[int32] = divBy2 <$> b
let b3: Maybe[int16] = divBy2x <$> b
assert(b.kind == Just and b.value == 9000)
assert(b2.kind == Just and b2.value == 4500)
assert(b3.kind == Just and b3.value == 4500)
proc mult(x: int16): int32 = x * 2
let
ca = Either[bool, int16](kind: Left, left: true)
cb = Either[bool, int16](kind: Right, right: 5)
cc: Either[bool, int32] = mult <$> ca
cd: Either[bool, int32] = mult <$> cb
assert(ca.kind == Left and ca.left == true)
assert(cb.kind == Right and cb.right == 5)
assert(cc.kind == Left and cc.left == true)
assert(cd.kind == Right and cd.right == 10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment