Church numerals: Difference between revisions
→All closures and a union for type-punning: Nim, simplify and improve code...
GordonBGood (talk | contribs) (→All closures and a union for type-punning: add more extensive Church functions and comments...) |
GordonBGood (talk | contribs) (→All closures and a union for type-punning: Nim, simplify and improve code...) |
||
Line 1,088:
===All closures and a union for type-punning===
Everything is an anonymous function, we dereference with a closure instead of a pointer,and the type-casting is hidden behind a union instead of behind a macro; the following code implements more extended Church functions such as Church subtraction and division than the task
<lang nim>import sugar
Line 1,095 ⟶ 1,094:
In = () -> int # a lazy thunk producing an int
Func = In -> In
MetaMetaChurch = MetaChurch -> MetaChurch
MetaPredChurch = PredChurch -> PredChurch
func unChurch(ch: Church): ChurchFunc = ch.chf▼
type # type Kind
Pun
upone: MetaChurch
▲ up: (T -> T) -> (T -> T)
uptwo: MetaMetaChurch
func
func liftpred(ch: Church): MetaPredChurch = Pun(normal: ch).preded
let
zeroChurch: Church =
oneChurch: Church =
succChurch =
addChurch =
((f: Func) => ((x: In) => ((ach f)(bch(f)x))))
(ch.lift2()((_: Church) => zeroChurch) oneChurch)
predChurch =
▲ multChurch = func(ach, bch: Church): Church =
▲ expChurch = proc(basech, expch: Church): Church =
(bch.lift2()(predChurch)(ach))
▲ isZeroChurch = proc(ch: Church): Church =
▲ makeChurch(func(f: Func): Func =
▲ # magic is here, reduces by one function...
▲ let prd = (gf: ChurchFunc) => ((hf: ChurchFunc) => hf(gf(f)))
▲ ch.unChurch.liftpred()(prd)((_: Func) => x)((t: Func) => t)).lower)
▲ minusChurch = proc(ach, bch: Church): Church =
# recursively counts times divisor can be subtracted from dividend...
divChurch = proc(dvdndch, dvsrch: Church): Church =
vch.lift2()( # test for zero
)(n.minusChurch(dvsrch)) # subtract one more divisor per loop
divr(dvdndch.succChurch)
▲ ((_: ChurchFunc) => (divr(vchf, d)).succ))( # not zero recurse
▲ zeroChurch.unChurch) # else terminate with zero
# conversions
proc toChurch(x: int): Church =
result = zeroChurch
for _ in 1 .. x: result = result.succChurch
let incr = (x: In) => (() => x() + 1)
proc toInt(ch: Church): int = ch
proc `$`(ch: Church): string = $(ch.toInt)
Line 1,180 ⟶ 1,156:
, fourChurch.expChurch(threeChurch)
, zeroChurch.isZeroChurch, oneChurch.isZeroChurch
, fourChurch.predChurch
, elevenChurch.minusChurch(threeChurch)
, elevenChurch.divChurch(threeChurch)
|