How to resolve the algorithm Church numerals step by step in the Elm programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Church numerals step by step in the Elm programming language

Table of Contents

Problem Statement

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals. In your language define:

You should:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Church numerals step by step in the Elm programming language

Source code in the elm programming language

module Main exposing ( main )

import Html exposing ( Html, text )

type alias Church a = (a -> a) -> a -> a

churchZero : Church a -- a Church constant
churchZero = always identity
 
succChurch : Church a -> Church a
succChurch ch = \ f -> f << ch f -- add one recursion
 
addChurch : Church a -> Church a -> Church a
addChurch chaf chbf = \ f -> chaf f << chbf f
 
multChurch : Church a -> Church a -> Church a
multChurch = (<<)
 
expChurch : Church a -> (Church a -> Church a) -> Church a
expChurch = (\ f x y -> f y x) identity -- `flip` inlined
 
churchFromInt : Int -> Church a
churchFromInt n = if n <= 0 then churchZero
                  else succChurch <| churchFromInt (n - 1)
 
intFromChurch : Church Int -> Int
intFromChurch cn = cn ((+) 1) 0 -- `succ` inlined
 
--------------------------- TEST -------------------------
main : Html Never
main =
  let cThree = churchFromInt 3
      cFour = succChurch cThree
  in [ addChurch cThree cFour
     , multChurch cThree cFour
     , expChurch cThree cFour
     , expChurch cFour cThree
     ] |> List.map intFromChurch
       |> Debug.toString |> text


module Main exposing (main)

import Html exposing (text)

-- the Church wrapper and functions...
type Church a = Church (Church a -> Church a)
              | ArityZero a -- treat a value as a function
applyChurch : Church a -> Church a -> Church a
applyChurch ch charg = case ch of Church chf -> chf charg
                                  ArityZero _ -> charg -- never happens!
composeChurch : Church a -> Church a -> Church a
composeChurch chl chr =
  case chl of Church chlf ->
                case chr of Church chrf -> Church <| \ f -> (chlf << chrf) f
                            otherwise -> chr -- never happens!
              otherwise -> chr -- never happens!

-- the Church Numeral functions...
churchZero : Church a
churchZero = Church <| always <| Church identity
churchOne : Church a
churchOne = Church identity
succChurch : Church a -> Church a
succChurch ch = Church <| \ f -> composeChurch f <| applyChurch ch f
addChurch : Church a -> Church a -> Church a
addChurch cha chb =
  Church <| \ f -> composeChurch (applyChurch cha f) (applyChurch chb f)
multChurch : Church a -> Church a -> Church a
multChurch cha chb = composeChurch cha chb
expChurch : Church a -> Church a -> Church a
expChurch chbs chexp = applyChurch chexp chbs
isZeroChurch : Church a -> Church a
isZeroChurch ch =
  applyChurch (applyChurch ch (Church <| \ _ -> churchZero)) churchOne
predChurch : Church a -> Church a
predChurch ch =
  Church <| \ f -> Church <| \ x ->
    let prdf = Church <| \ g -> Church <| \ h ->
                            applyChurch h (applyChurch g f)
    in applyChurch (applyChurch (applyChurch ch prdf)
                                (Church <| \ _ -> x)) <| Church identity
subChurch : Church a -> Church a -> Church a
subChurch cha chb = applyChurch (applyChurch chb <| Church predChurch) cha 

divChurch : Church a -> Church a -> Church a
divChurch chdvdnd chdvsr =
  let divr n =
        let loop v = Church <| \ _ -> succChurch <| divr v
            tst v = applyChurch (applyChurch v <| loop v) churchZero
        in tst <| subChurch n chdvsr
  in divr <| succChurch chdvdnd

-- conversion functions...
intToChurch : Int -> Church a
intToChurch i = List.foldl (\ _ ch -> succChurch ch) churchZero (List.range 1 i)
churchToInt : Church Int -> Int
churchToInt ch =
  let succInt = Church <| \ ach -> case ach of ArityZero v -> ArityZero (v + 1)
                                               otherwise -> ach -- never happens!
  in case applyChurch (applyChurch ch succInt) <| ArityZero 0 of
       ArityZero r -> r
       otherwise -> -1 -- never happens!

--------------------------------------TEST--------------------------------------
main : Html.Html Never
main =
  let chThree = intToChurch 3
      chFour = succChurch chThree
      chEleven = intToChurch 11
      chTwelve = succChurch chEleven
  in [ addChurch chThree chFour
     , multChurch chThree chFour
     , expChurch chThree chFour
     , expChurch chFour chThree
     , isZeroChurch churchZero
     , isZeroChurch chThree
     , predChurch chFour
     , subChurch chEleven chThree
     , divChurch chEleven chThree
     , divChurch chTwelve chThree
     ] |> List.map (String.fromInt << churchToInt)
       |> String.join ", " |> text


  

You may also check:How to resolve the algorithm Four is magic step by step in the APL programming language
You may also check:How to resolve the algorithm Digital root step by step in the Oforth programming language
You may also check:How to resolve the algorithm Farey sequence step by step in the Java programming language
You may also check:How to resolve the algorithm Run-length encoding step by step in the Fan programming language
You may also check:How to resolve the algorithm Jump anywhere step by step in the Haskell programming language