@shirleyQuirk, I have been intrigued by this ever since I first saw this post, 
and [extended your excellent 
contribution](http://rosettacode.org/wiki/Church_numerals#All_closures_and_a_union_for_type-punning)
 to add the Church Numeral functions of the isZeroChurch predicate, the Church 
predecessor function needed for the Church subtraction function, and the Church 
division function. To do this, I had to extend your type "punning" to include 
that needed for the Church predecessor function, as although one can write this 
without the level of punning and test it, it can't then be used by the Church 
subtraction function as it then has a chained use with variable "Kind"'s of 
rank of functions depending on the application in the chain, which leads to a 
non-determinable "infinite" type race: one needs to "pun" the arguments so that 
a consistent "Church -> Church" results to avoid this type race.

The Church division function is even more interesting as it implements the 
algorithm "count the number of loops it takes to subtract the divisor for the 
dividend until zero is reached", using a unwrapped version of the isZeroChurch 
function as the predicate which controls the branching if not zero or zero. 
Rather than use the Y-Combinator for the recursion, I just did a direct 
function call since Nim supports direct proc/func recursion.

I believe that once one knows the techniques to write these extended Church 
functions, one can write any of the other many Church functions.

I have also contributed the extended functions in Haskell on that same page for 
comparison, both using raw casting/coercion, and the GHC Haskell "RankNTypes" 
extension, which automates the "punning" for functions of differing ranks as to 
Kind.

To show it can also be done in other languages, I also added the extended 
functions to the C# and F# contributions on the page, although the F# solution 
is extremely slow due to having to use a kluge to do the function rank 
conversion in using what is essentially a DotNet dynamic type; F# does have 
delegates as for the C# solution but they aren't implemented the same way in 
that the F# type inference applies to the F# version and it doesn't allow the 
automatic rank conversion.

Reply via email to