I did make sure that division worked so I'm not surprised it was easy to add, 
but I'm surprised by the elegance of your predicate function. I've only seen 
them based upon church pairs before, what was your inspiration?

Purely cosmetically speaking, I think all the -chuch suffixes are distracting. 
And i thought about cleaning up some of the meta boiler plate: 
    
    
    import sugar, macros,std/genasts
    template Meta(T:type):type = T->T
    template Sesqui[T](t:typedesc[(T->T)->(T->T)]):type =
      (T->T->T)->(T->T->T)
    type
      In = () -> int # a lazy thunk producing an int
      Func = Meta In
      Church = Meta Func
    
    macro lifter(x:untyped):untyped =
      result = x
      let ret_ty = x[3][0]
      let param_ty = x[3][1][1]
      let param_name = x[3][1][0]
      result[6] = genast(ret_ty,param_ty,param_name):
        type Pun{.union.}=object
          l:param_ty
          h:ret_ty
        Pun(l:param_name).h
    
    func ²[T](x:T):Meta T{.lifter.}
    func ⁴[T](x:T):Meta Meta T{.lifter.}
    func ³(x:Church):Meta Sesqui Church {.lifter.}
    
    
    Run

Similarly, templates for the common lambda definitions might make things more 
readable, if lambda calculus syntax counts as readable: 
    
    
    template  λc(body:untyped):untyped =(proc(c{.inject.}: Church):Church = 
body)
    #etc for λf:Func, λx:In, λab:Church
    #and maybe for λg:Func λy:In
    #so that pred can be written like so:
    let pred = λc λf do:
          let prd = (gf: In->In->In) => ((hf: In->In) => hf gf f)
          # magic is here, reduces by one function level...
          λx (c.³)(prd)( λg x )( λy y )
    
    
    Run

Reply via email to