Church numerals: Difference between revisions

m
syntax highlighting fixup automation
m (→‎{{header|OCaml}}: adjust code ordering and comments slightly...)
m (syntax highlighting fixup automation)
Line 34:
Implementing '''churchFromInt''' as a fold seems to protect Applescript from overflowing its (famously shallow) stack with even quite low Church numerals.
 
<langsyntaxhighlight lang=applescript>--------------------- CHURCH NUMERALS --------------------
 
-- churchZero :: (a -> a) -> a -> a
Line 199:
on succ(x)
1 + x
end succ</langsyntaxhighlight>
{{Out}}
<pre>{7, 12, 64, 81}</pre>
Line 205:
=={{header|C sharp|C#}}==
The following implementation using the "RankNTypes" facilities as per Haskell by using a delegate to represent the recursive functions, and implements the more advanced Church functions such as Church subtraction and division that wouldn't be possible otherwise; if the ability to map functions of higher ranked "Kind's" to be the same type were not included, the Church type would be an infinite undecidable type:
<langsyntaxhighlight lang=csharp>using System;
public delegate Church Church(Church f);
Line 255:
Console.WriteLine($"{pred4} {sub43} {div11by3} {div12by3}");
}
}</langsyntaxhighlight>
{{out}}
<pre>7 12 64 81 1 3 1 3 4</pre>
Line 264:
Chapel doesn't have first class closure functions, so they are emulated using the default method of inherited classes with fields containing the necessary captured values. The instantiated classes are `shared` (reference counted) to avoid any chance that references within their use causes memory leaks. As with some other statically typed languages, Chapel's implementation of generics is not "type complete" as to automatically doing beta reduction, so the following code implements a recursively defined class as a wrapper so as to be able to handle that, just as many other statically-typed languages need to do:
{{trans|F#}}
<langsyntaxhighlight lang=chapel>class Church { // identity Church function by default
proc this(f: shared Church): shared Church { return f; }
}
Line 441:
write(intFromChurch(subChurch(ch11, ch3)), ", ");
write(intFromChurch(divChurch(ch11, ch3)), ", ");
writeln(intFromChurch(divChurch(ch12, ch3)));</langsyntaxhighlight>
{{out}}
<pre>7, 12, 81, 64, 1, 0, 3, 0, 8, 3, 4</pre>
Line 448:
=={{header|Clojure}}==
{{trans|Raku}}
<langsyntaxhighlight lang=clojure>(defn zero [f] identity)
(defn succ [n] (fn [f] (fn [x] (f ((n f) x)))))
(defn add [n,m] (fn [f] (fn [x] ((m f)((n f) x)))))
Line 465:
(doseq [n [(add three four) (mult three four)
(power three four) (power four three)]]
(println (to-int n)))</langsyntaxhighlight>
{{Out}}
<pre>7
Line 476:
Although the Crystal language is by no means a functional language, it does offer the feature of "Proc"'s/lambda's which are even closures, meaning that they can capture environment state from outside the scope of their body. Using these plus a structure to act as a wrapper for the recursive typed Church functions and the Union types to be able to eliminate having to use side effects, the following code for the Extended Church Numeral functions was written (this wasn't written generically, but that isn't that important to the Task):
{{trans|F#}}
<langsyntaxhighlight lang=crystal>struct Church # can't be generic!
getter church : (Church -> Church) | Int32
def initialize(@church) end
Line 594:
div2 = churchToInt(divChurch.call(ch12, ch3))
print("#{add} #{mult} #{exp1} #{exp2} #{iszero1} #{iszero2} ")
print("#{pred1} #{pred2} #{sub} #{div1} #{div2}\r\n")</langsyntaxhighlight>
{{out}}
<pre>7 12 81 64 1 0 3 0 8 3 4</pre>
Line 603:
 
{{trans|Haskell}}
<langsyntaxhighlight lang=elm>module Main exposing ( main )
 
import Html exposing ( Html, text )
Line 641:
, expChurch cFour cThree
] |> List.map intFromChurch
|> Debug.toString |> text</langsyntaxhighlight>
{{out}}
<pre>[7,12,81,64]</pre>
Line 648:
 
{{trans|F#}}
<langsyntaxhighlight lang=elm>module Main exposing (main)
 
import Html exposing (text)
Line 729:
, divChurch chTwelve chThree
] |> List.map (String.fromInt << churchToInt)
|> String.join ", " |> text</langsyntaxhighlight>
{{out}}
<pre>7, 12, 81, 64, 1, 0, 3, 8, 3, 4</pre>
Line 737:
=={{header|Erlang}}==
{{trans|Raku}}
<langsyntaxhighlight lang=erlang>-module(church).
-export([main/1, zero/1]).
zero(_) -> fun(F) -> F end.
Line 757:
[add(Three,Four), mult(Three,Four),
power(Three,Four), power(Four,Three)]).
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 770:
The following code uses the usual F# recommended work around to implement Haskell's "RankNTypes" so that the Church functions can represent functions of any Kind rank by using an abstract Interface type to represent it and create and instantiate a new type for every invocation of the wrapped function as required to implement this more complete set of Church functions, especially subtraction and division:
{{trans|C sharp}}
<langsyntaxhighlight lang=fsharp>type IChurch =
abstract Apply : ('a -> 'a) -> ('a -> 'a)
 
Line 820:
; divChurch c12 c3
] |> List.map chtoi |> printfn "%A"
0 // return an integer exit code</langsyntaxhighlight>
{{out}}
<pre>[7; 12; 81; 64; 1; 0; 2; 8; 3; 4]</pre>
Line 831:
The following code uses F#'s Discriminated Unions to express the multi-ranked function Kinds that work like C# delegates; this code still uses side effects to convert the resulting Church Numerals, which is a facility that F# offers so we may as well use it since it is easily expressed:
{{trans|C sharp}}
<langsyntaxhighlight lang=fsharp>// types...
type Church = Church of (Church -> Church)
let applyChurch (Church chf) charg = chf charg
Line 888:
; division c12 c3
] |> List.map churchToInt |> printfn "%A"
0 // return an integer exit code</langsyntaxhighlight>
{{out}}
<pre>[7; 12; 81; 64; 1; 0; 2; 8; 3; 4]</pre>
Line 897:
One can achieve functional purity (without side effects) within the "RankNTypes" functions defined using the recursive Discriminated Unions as per the above code by including a tag of the "arity zero" case which just wraps a value. The following code uses that to be able to convert from Church Numerals to integers without using side effects:
 
<langsyntaxhighlight lang=fsharp>#nowarn "25" // eliminate incomplete pattern match warning
 
// types...
Line 956:
; divChurch c12 c3
] |> List.map churchToInt |> printfn "%A"
0 // return an integer exit code</langsyntaxhighlight>
{{out}}
<pre>[7; 12; 81; 64; 1; 0; 2; 8; 3; 4]</pre>
Line 974:
 
=={{header|Go}}==
<langsyntaxhighlight lang=go>package main
 
import "fmt"
Line 1,051:
fmt.Println("four ^ three ->", four.pow(three).toInt())
fmt.Println("5 -> five ->", intToChurch(5).toInt())
}</langsyntaxhighlight>
 
{{out}}
Line 1,065:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang=Groovy>class ChurchNumerals {
static void main(args) {
 
Line 1,099:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,116:
 
The following code implements the more complex Church functions using `unsafeCoerce` to avoid non-decidable infinite types:
<langsyntaxhighlight lang=haskell>import Unsafe.Coerce ( unsafeCoerce )
 
type Church a = (a -> a) -> a -> a
Line 1,182:
, divChurch cEleven cThree
, divChurch cTwelve cThree
]</langsyntaxhighlight>
{{Out}}
<pre>[7, 12, 81, 64, 1, 0, 3, 8, 3, 4]</pre>
Line 1,192:
 
The following code uses a wrapper `newtype` and the "RankNTypes" GHC Haskell extension to avoid the requirement for the unsafe coercion used above:
<langsyntaxhighlight lang=haskell>{-# LANGUAGE RankNTypes #-}
 
newtype Church = Church { unChurch :: forall a. (a -> a) -> a -> a }
Line 1,257:
, divChurch cEleven cThree
, divChurch cTwelve cThree
]</langsyntaxhighlight>
{{out}}
<pre>[7, 12, 81, 64, 1, 0, 3, 8, 3, 4]</pre>
Line 1,266:
Implementation:
 
<langsyntaxhighlight lang=J>chget=: {{(0;1;1;1) {:: y}}
 
chset=: {{
Line 1,289:
chExp=: {{(x ^&chget y) chset y}}
int2ch=: {{y chset ch0 ''}}
ch2int=: chget</langsyntaxhighlight>
 
Here, we are using J's [https://www.jsoftware.com/help/dictionary/d202n.htm power conjunction] in a [https://www.jsoftware.com/help/dictionary/d610.htm gerund representation] of a function.
Line 1,295:
Task example:
 
<langsyntaxhighlight lang=J>three=: chNext^:3 ch0''
four=: chNext^:4 ch0''
sixtyfour=: four chExp three
Line 1,309:
chget eightyone
81
</syntaxhighlight>
</lang>
 
Illustration of the difference between a church numeral and the represented functions:
 
<syntaxhighlight lang=J>
<lang J>
three apply 0
3
Line 1,324:
0
four apply 10
160</langsyntaxhighlight>
 
It's perhaps worth noting that J supports repeated negative applications of invertible functions:
 
<langsyntaxhighlight lang=J> four=: 4 chset ch0 +:`''
four apply 10
160
Line 1,336:
762939453125000
(sixtyfour chSub three chExp 4 chset ch0 5x&*`'') apply 10x^20
131072000</langsyntaxhighlight>
 
=={{header|Java}}==
{{Works with|Java|8 and above}}
<langsyntaxhighlight lang=java>package lvijay;
 
import java.util.concurrent.atomic.AtomicInteger;
Line 1,405:
System.out.println(" 8=" + toInt(toChurchNum(8))); // prints 8
}
}</langsyntaxhighlight>
{{Out}}
<pre>
Line 1,418:
 
=={{header|Javascript}}==
<langsyntaxhighlight lang=javascript>(() => {
'use strict';
 
Line 1,525:
// MAIN ---
console.log(JSON.stringify(main()));
})();</langsyntaxhighlight>
{{Out}}
<pre>[7,12,64,81]</pre>
Line 1,531:
In jq, the Church encoding of the natural number $m as per the definition of this task would
be church(f; $x; $m) defined as:
<langsyntaxhighlight lang=jq>def church(f; $x; $m):
if $m == 0 then .
elif $m == 1 then $x|f
else church(f; $x; $m - 1)
end;</langsyntaxhighlight>
 
This is because jq's identify function is `.`.
Line 1,541:
However, since jq functions are filters,
the natural definition would be:
<langsyntaxhighlight lang=jq>def church(f; $m):
if $m < 0 then error("church is not defined on negative integers")
elif $m == 0 then .
elif $m == 1 then f
else church(f; $m - 1) | f
end;</langsyntaxhighlight>
So for example "church 0" can be realized as `church(f; 0)`.
 
Line 1,555:
=={{header|Julia}}==
We could overload the Base operators, but that is not needed here.
<langsyntaxhighlight lang=julia>
id(x) = x -> x
zero() = x -> id(x)
Line 1,576:
 
runtests()
</langsyntaxhighlight> {{output}} <pre>
Church 3 + Church 4 = 7
Church 3 * Church 4 = 12
Line 1,585:
===Extended Church Functions in Julia===
 
<langsyntaxhighlight lang=julia>id = x -> x
always(f) = d -> f
struct Church # used for "infinite" Church type resolution
Line 1,629:
end
runtests()</langsyntaxhighlight>
{{out}}
<pre>Church 3 + Church 4 = 7
Line 1,647:
=={{header|Lambdatalk}}==
 
<langsyntaxhighlight lang=Scheme>
{def succ {lambda {:n :f :x} {:f {:n :f :x}}}}
{def add {lambda {:n :m :f :x} {{:n :f} {:m :f :x}}}}
Line 1,663:
3^4 = {church {power {three} {four}}} -> 81
4^3 = {church {power {four} {three}}} -> 64
</syntaxhighlight>
</lang>
 
=={{header|Lua}}==
<langsyntaxhighlight lang=lua>
function churchZero()
return function(x) return x end
Line 1,717:
print("'three' + 'four' =", churchToNum(churchAdd(three, four)))
print("'three' ^ 'four' =", churchToNum(churchExp(three, four)))
print("'four' ^ 'three' =", churchToNum(churchExp(four, three)))</langsyntaxhighlight>
{{out}}
<pre>'three' = 3
Line 1,729:
===Macros and Pointers===
Using type erasure, pure functions, and impenetrably terse syntax to keep to the spirit of the untyped lambda calculus:
<langsyntaxhighlight lang=nim>import macros, sugar
type
Fn = proc(p: pointer): pointer{.noSideEffect.}
Line 1,778:
let four = 4.toChurch
echo [three+four, three*four, three^four, four^three]
</syntaxhighlight>
</lang>
 
===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 requires:
<langsyntaxhighlight lang=nim>import sugar
 
type # use a thunk closure as a data type...
Line 1,853:
, elevenChurch.divChurch(threeChurch)
, twelveChurch.divChurch(threeChurch)
]</langsyntaxhighlight>
{{out}}
<pre>[7, 12, 81, 64, 1, 0, 8, 3, 4]</pre>
Line 1,862:
Although Nim is by no means a functional language, we can implement this without using type erasure or raw type casting/"punning" by using object variants to represent what the Haskell/OCaml languages do with "forall RankNTypes" so that one wrapper represents functions nested to any Kind rank and also the actual value (int in this case). Generic types don't work so well here as the generic type must be known when instantiated in Nim, so we can't generate an object of a generic type from an int. However, what does work means that casting/"punning" isn't necessary while still being able to evaluate the Church Numeral representations to values without using side effects, as per the following code:
{{trans|F#}}
<langsyntaxhighlight lang=nim>import sugar
 
type
Line 1,951:
subChurch(c11, c3), " ",
divChurch(c11, c3), " ",
divChurch(c12, c3)</langsyntaxhighlight>
{{out}}
<pre>7 12 81 64 1 0 3 8 3 4</pre>
Line 1,961:
 
The extended Church functions as per the "RankNTypes" Haskell version have been added...
<langsyntaxhighlight lang=OCaml>(* Using type as suggested in https://stackoverflow.com/questions/43426709/does-ocamls-type-system-prevent-it-from-modeling-church-numerals
This is an explicitly polymorphic type : it says that f must be of type ('a -> 'a) -> 'a -> 'a for any possible a "at same time".
*)
Line 2,064:
;;
 
print_endline result</langsyntaxhighlight>
{{out}}
<pre>[ 3; 4; 7; 12; 64; 81; 11; 12; 1; 0; 2; 8; 3; 4 ]</pre>
 
=={{header|Octave}}==
<langsyntaxhighlight lang=Octave>
zero = @(f) @(x) x;
succ = @(n) @(f) @(x) f(n(f)(x));
Line 2,093:
mul(three, four),
pow(three, four),
pow(four, three)})</langsyntaxhighlight>
{{out}}
<pre>ans =
Line 2,101:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang=perl>use 5.020;
use feature qw<signatures>;
no warnings qw<experimental::signatures>;
Line 2,138:
power->( four )->( three ),
power->( three )->( four ),
);</langsyntaxhighlight>
{{out}}
<pre>7 12 64 81</pre>
Line 2,144:
=={{header|Phix}}==
{{trans|Go}}
<!--<langsyntaxhighlight lang=Phix>(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Line 2,234:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"four ^ three -&gt; %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tointch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">powch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">four</span><span style="color: #0000FF;">,</span><span style="color: #000000;">three</span><span style="color: #0000FF;">)))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 -&gt; five -&gt; %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tointch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inttoch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)))</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,247:
 
=={{header|PHP}}==
<langsyntaxhighlight lang=php><?php
$zero = function($f) { return function ($x) { return $x; }; };
 
Line 2,302:
print("\n");
}
?></langsyntaxhighlight>
{{Out}}
<pre>7
Line 2,312:
=={{header|Prolog}}==
Prolog terms can be used to represent church numerals.
<langsyntaxhighlight lang=prolog>church_zero(z).
 
church_successor(Z, c(Z)).
Line 2,352:
!,
maplist(format('~w '), [ISum, IProduct, IPower43, IPower34]),
nl.</langsyntaxhighlight>
{{out}}
<pre>
Line 2,360:
=={{header|Python}}==
{{Works with|Python|3.7}}
<langsyntaxhighlight lang=python>'''Church numerals'''
 
from itertools import repeat
Line 2,491:
 
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>[7, 12, 64, 81]</pre>
Line 2,499:
Quackery is a postfix language, so these are Reverse Polish Church numerals.
 
<langsyntaxhighlight lang=Quackery> [ this nested ] is zero ( --> cn )
 
[ this nested join ] is succ ( cn --> cn )
Line 2,539:
four three mul cn->n echo sp
four three exp cn->n echo sp
three four exp cn->n echo</langsyntaxhighlight>
 
'''Output:'''
Line 2,547:
{{trans|Racket}}
R was inspired by Scheme and this task offers little room for creativity. As a consequence, our solution will inevitably look a lot like Racket's. Therefore, we have made this easy and just translated their solution. Alternative implementations, denoted by asterisks in their code, are separated out and denoted by "[...]Alt".
<langsyntaxhighlight lang=rsplus>zero <- function(f) {function(x) x}
succ <- function(n) {function(f) {function(x) f(n(f)(x))}}
add <- function(n) {function(m) {function(f) {function(x) m(f)(n(f)(x))}}}
Line 2,561:
churchToNat(mult(three)(four))
churchToNat(expt(three)(four))
churchToNat(expt(four)(three))</langsyntaxhighlight>
{{out}}
<pre>> churchToNat(add(three)(four))
Line 2,575:
[1] 64</pre>
Alternative versions (Racket's, again):
<langsyntaxhighlight lang=rsplus>zeroAlt <- function(x) identity
one <- function(f) f #Not actually requested by the task and only used to define Alt functions, so placed here.
oneAlt <- identity
Line 2,582:
addAlt <- function(n) n(succ)
multAlt <- function(n) {function(m) m(add(n))(zero)}
exptAlt <- function(n) {function(m) m(mult(n))(one)}</langsyntaxhighlight>
Extra tests - mostly for the alt versions - not present in the Racket solution:
<langsyntaxhighlight lang=rsplus>churchToNat(addAlt(three)(four))
churchToNat(multAlt(three)(four))
churchToNat(exptAlt(three)(four))
Line 2,590:
churchToNat(succ(four))
churchToNat(succAlt(four))
churchToNat(succAltAlt(four))</langsyntaxhighlight>
{{out}}
<pre>> churchToNat(addAlt(three)(four))
Line 2,614:
 
===Extended Church Functions in R===
<langsyntaxhighlight lang=rsplus>const <- function(f) {function(d) f}
zero <- const(identity)
one <- identity
Line 2,646:
churchToNat(subt(eleven)(three))
churchToNat(div(eleven)(three))
churchToNat(div(twelve)(three))</langsyntaxhighlight>
{{out}}
<pre>[1] 7
Line 2,662:
=={{header|Racket}}==
 
<langsyntaxhighlight lang=racket>#lang racket
(define zero (λ (f) (λ (x) x)))
Line 2,697:
(church->nat ((mult three) four))
(church->nat ((expt three) four))
(church->nat ((expt four) three))</langsyntaxhighlight>
 
{{out}}
Line 2,711:
===Traditional subs and sigils===
{{trans|Python}}
<syntaxhighlight lang=raku perl6line>constant $zero = sub (Code $f) {
sub ( $x) { $x }}
 
Line 2,750:
$power( $four )( $three ),
$power( $three )( $four ),
;</langsyntaxhighlight>
===Arrow subs without sigils===
{{trans|Julia}}
<syntaxhighlight lang=raku perl6line>my \zero = -> \f { -> \x { x }}
my \succ = -> \n { -> \f { -> \x { f.(n.(f)(x)) }}}
my \add = -> \n { -> \m { -> \f { -> \x { m.(f)(n.(f)(x)) }}}}
Line 2,770:
power.( four )( three ),
power.( three )( four ),
;</langsyntaxhighlight>
{{out}}
<pre>(7 12 64 81)</pre>
Line 2,780:
 
===Traditional methods===
<langsyntaxhighlight lang=ruby>def zero(f)
return lambda {|x| x}
end
Line 2,824:
power(Three, Four),
power(Four, Three) ].map {|f| int_from_couch(f) }
</syntaxhighlight>
</lang>
{{Out}}
<pre>7
Line 2,832:
 
===Procs all the way down===
<langsyntaxhighlight lang=ruby>Zero = proc { |f| proc { |x| x } }
 
Succ = proc { |n| proc { |f| proc { |x| f[n[f][x]] } } }
Line 2,860:
Mult[Three, Four],
Power[Three, Four],
Power[Four, Three] ].map(&ToInt)</langsyntaxhighlight>
{{Out}}
<pre>7
Line 2,868:
 
=={{header|Rust}}==
<langsyntaxhighlight lang=rust>use std::rc::Rc;
use std::ops::{Add, Mul};
 
Line 2,965:
println!("three ^ four =\t{}", i32::from(&(three().exp(four()))));
println!("four ^ three =\t{}", i32::from(&(four().exp(three()))));
}</langsyntaxhighlight>
{{Out}}
<pre>three = 3
Line 2,975:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang=Standard ML>
val demo = fn () =>
let
Line 2,996:
end;
</syntaxhighlight>
</lang>
output
<langsyntaxhighlight lang=Standard ML>
demo ();
7
Line 3,004:
64
81
</syntaxhighlight>
</lang>
 
=={{header|Swift}}==
<langsyntaxhighlight lang=swift>func succ<A, B, C>(_ n: @escaping (@escaping (A) -> B) -> (C) -> A) -> (@escaping (A) -> B) -> (C) -> B {
return {f in
return {x in
Line 3,083:
let d = unchurch(exp(mult(three)(church(1)))(four))
 
print(a, b, c, d)</langsyntaxhighlight>
{{out}}
<pre>7 12 64 81</pre>
Line 3,090:
In Tailspin functions can be used as parameters but currently not as values, so they need to be wrapped in processor (object) instances.
===Using lambda calculus compositions===
<langsyntaxhighlight lang=tailspin>
processor ChurchZero
templates apply&{f:}
Line 3,166:
$four -> Power&{exp: $three} -> intFromChurch -> '$;
' -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,177:
===Using basic mathematical definitions===
Less efficient but prettier functions can be gotten by just implementing Add as a repeated application of Successor, Multiply as a repeated application of Add and Power as a repeated application of Multiply
<langsyntaxhighlight lang=tailspin>
processor ChurchZero
templates apply&{f:}
Line 3,236:
$four -> power&{exp: $three} -> intFromChurch -> '$;
' -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,247:
=={{header|Wren}}==
{{trans|Lua}}
<langsyntaxhighlight lang=ecmascript>class Church {
static zero { Fn.new { Fn.new { |x| x } } }
 
Line 3,275:
System.print("three * four -> %(Church.toInt(Church.mul(three, four)))")
System.print("three ^ four -> %(Church.toInt(Church.pow(three, four)))")
System.print("four ^ three -> %(Church.toInt(Church.pow(four, three)))")</langsyntaxhighlight>
 
{{out}}
Line 3,288:
 
=={{header|zkl}}==
<langsyntaxhighlight lang=zkl>class Church{ // kinda heavy, just an int + fcn churchAdd(ca,cb) would also work
fcn init(N){ var n=N; } // Church Zero is Church(0)
fcn toInt(f,x){ do(n){ x=f(x) } x } // c(3)(f,x) --> f(f(f(x)))
Line 3,296:
fcn pow(c) { self(n.pow(c.n)) }
fcn toString{ String("Church(",n,")") }
}</langsyntaxhighlight>
<langsyntaxhighlight lang=zkl>c3,c4 := Church(3),c3.succ();
f,x := Op("+",1),0;
println("f=",f,", x=",x);
Line 3,305:
println("%s^%s=%d".fmt(c3,c4, (c3.pow(c4)).toInt(f,x) ));
println();
T(c3+c4,c3*c4,c4.pow(c3),c3.pow(c4)).apply("toInt",f,x).println();</langsyntaxhighlight>
{{out}}
<pre>
Line 3,318:
OK, that was the easy sleazy cheat around way to do it.
The wad of nested functions way is as follows:
<langsyntaxhighlight lang=zkl>fcn churchZero{ return(fcn(x){ x }) } // or fcn churchZero{ self.fcn.idFcn }
fcn churchSucc(c){ return('wrap(f){ return('wrap(x){ f(c(f)(x)) }) }) }
fcn churchAdd(c1,c2){ return('wrap(f){ return('wrap(x){ c1(f)(c2(f)(x)) }) }) }
Line 3,325:
fcn churchToInt(c,f,x){ c(f)(x) }
fcn churchFromInt(n){ c:=churchZero; do(n){ c=churchSucc(c) } c }
//fcn churchFromInt(n){ (0).reduce(n,churchSucc,churchZero) } // what ever</langsyntaxhighlight>
<langsyntaxhighlight lang=zkl>c3,c4 := churchFromInt(3),churchSucc(c3);
f,x := Op("+",1),0; // x>=0, ie natural number
T(c3,c4,churchAdd(c3,c4),churchMul(c3,c4),churchPow(c4,c3),churchPow(c3,c4))
.apply(churchToInt,f,x).println();</langsyntaxhighlight>
{{out}}
<pre>
10,327

edits