Skip to content

Instantly share code, notes, and snippets.

@mflamer
Created October 28, 2013 18:50
Show Gist options
  • Save mflamer/7202443 to your computer and use it in GitHub Desktop.
Save mflamer/7202443 to your computer and use it in GitHub Desktop.
NimSum 0.1 - Using generics to encode enough type information to act as statically checked Sum types commonly found in functional languages.
{.hint[XDeclaredButNotUsed]: off.}
import baseutils, typetraits, macros
#----------------------------------------------------
# SumType
#----------------------------------------------------
template isVal(x: expr): expr = x.type.type is x.type
template inj(a, x: expr): expr =
cast[a[x.type]](x)
template `<=`(v: expr, m: expr, action: stmt): stmt {.immediate.} =
block:
let v = proj(proj(m))
action
template `===`(m, v: expr, action: stmt): stmt {.immediate.} =
#echo(m.proj.type.name & " " & v().type.name)
when m.proj.type.name == v().type.name:
block:
let val {.inject.} = proj(proj(m))
action
template `=~=`(m, v: expr, action: stmt): stmt {.immediate.} =
#echo(m.proj.type.name0 & " " & v)
when m.proj.type.name0 == "T"&v:
block:
let val {.inject.} = proj(proj(m))
action
#proc proj[T,S](x: S[T]): T = T(x) # I wish we could do this!
##-------------------------------------------------------------
## Maybe
##-------------------------------------------------------------
type
TMaybe[V,T] = distinct V
TJust[T] = distinct T
TNone[T] = distinct T
proc proj[V,T](x: TMaybe[V,T]): V = V(x)
proc proj[T](x: TJust[T]): T = T(x)
proc proj(x: TNone): TUnit = Unit
proc None(): TNone[TUnit] {.inline.} =
inj(TNone, Unit)
proc Just[T](x: T): TJust[T] {.inline.} =
inj(TJust, x)
proc Just[T](): TJust[T] {.inline.} =
var temp:T
inj(TJust,temp)
converter toMaybe[T](m: TJust[T]): TMaybe[TJust[T],T] =
cast[TMaybe[TJust[T],T]](m)
converter toMaybe[T](m: TNone[T]): TMaybe[TNone[T],T] =
cast[TMaybe[TNone[T],T]](m)
proc `$`[V,T](s: TMaybe[V,T]): string =
s === Just[T]:
return "Just(" & $val & ")"
s === None:
return "None"
#Tests ----------------------------
when isMainModule:
type
pnt = tuple[x: int,y: int]
var tpnt: tuple[x: int,y: int]
tpnt = (69,96)
var test = Just(69)
var test2 = None()
#echo(test)
#w <= test:
# echo("damn I'm good " & $w)
##-------------------------------------------------------------
## Binary Tree
##-------------------------------------------------------------
type
TBTree[V,T] = distinct V
TNode[VL,VR,T] = tuple[le:TBTree[VL,T], ri:TBTree[VR,T]]
TLeaf[T] = distinct T
proc proj[V,T](x: TBTree[V,T]): V = V(x)
proc proj[VL,VR,T](x: TNode[VL,VR,T]): tuple[le:TBTree[VL,T], ri:TBTree[VR,T]] =
tuple[le:TBTree[VL,T], ri:TBTree[VR,T]](x)
proc proj[T](x: TLeaf[T]): T = T(x)
proc Node[VL,VR,T](left: TBTree[VL,T], right: TBTree[VR,T]): TNode[VL,VR,T] =
result.le = left
result.ri = right
proc Node[VL,VR,T](): TNode[VL,VR,T] =
var temp: tuple[le:TBTree[VL,T], ri:TBTree[VR,T]]
result = cast[TNode[VL,VR,T]](temp)
proc Leaf[T](x: T): TLeaf[T] {.inline.} =
inj(TLeaf, x)
proc Leaf[T](): TLeaf[T] {.inline.} =
return result
converter toTree[VL,VR,T](m: TNode[VL,VR,T]): TBTree[TNode[VL,VR,T],T] =
cast[TBTree[TNode[VL,VR,T],T]](m)
converter toTree[T](m: TLeaf[T]): TBTree[TLeaf[T],T] =
cast[TBTree[TLeaf[T],T]](m)
proc `$`[V,T](s: TBTree[V,T]): string =
#echo(s.type.name)
s =~= "Node":
return "Node- \n" & $val.le & "\n" & $val.ri
s === Leaf[T]:
return "Leaf(" & $val & ")"
var
tl = Leaf(69)
tre0 = Node(tl,tl)
tre = Node(tl,tre0)
echo(tre.toTree)
#echo(tre)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment