Created
October 28, 2013 18:50
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{.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