вычитание церковных цифр в F # - PullRequest
2 голосов
/ 06 октября 2019

Я новичок в функциональном программировании и F #. В качестве упражнения я пытаюсь реализовать церковные цифры.
Сначала я закодировал числа как:

let ZERO = fun p x -> x
let ONE = fun p x -> p x
let TWO = fun p x -> p(p x)
let THREE = fun p x -> p(p(p x))
let FIVE = fun p x ->p(p(p(p(p x))))
... etc

Затем я написал вспомогательную функцию, чтобы посмотреть, работают ли мои числа:

let toInt p = p (fun x->x+1) 0 

дляпример:

toInt (THREE) |> printfn "%A" 

печатает 3, как и ожидалось.
Также я реализовал некоторые арифметические функции:

let INC = fun n f x -> f((n(f))(x)) //incrementation
let DEC = fun n f x -> n (fun g -> fun h -> h(g f))(fun y->x)(fun y-> y) //decrementation      
let ADD = fun m n -> n(INC)(m) //addition
let MUL = fun m n s z -> n(m s) z //multiplication
let POW = fun m n -> n(MUL m)ONE //exponential

Кажется, что все они работают нормально:

toInt (INC THREE) |> printfn "%A"  //prints 4
toInt (DEC THREE) |> printfn "%A" //prints 2
toInt (ADD THREE FIVE) |> printfn "%A" //prints 8
toInt (MUL THREE FIVE) |> printfn "%A"  //prints 15
toInt (POW THREE FIVE) |> printfn "%A"  //prints 243

Но я действительно изо всех сил пытаюсь реализовать вычитание:

let SUB = fun m n ->  n(DEC m)
toInt (SUB FIVE THREE) |> printfn "%A" //gives 64

Вышеупомянутый метод выглядит как некая экспонента вместо вычитания.
Я также пытался (как предполагает вики):

let SUB = fun m n ->  n(DEC)m

но это приводит к несовпадению типов, когда я пытаюсь его использовать:

toInt (SUB FIVE THREE) |> printfn "%A"  

"Type mismatch. Expecting a
    '(((('a -> 'b) -> ('b -> 'c) -> 'c) -> ('d -> 'e) -> ('f -> 'f) -> 'g) -> 'a -> 'e -> 'g) -> (('h -> 'h) -> 'h -> 'h) -> (int -> int) -> int -> 'i'    
but given a
    '(((('a -> 'b) -> ('b -> 'c) -> 'c) -> ('d -> 'e) -> ('f -> 'f) -> 'g) -> (('a -> 'b) -> ('b -> 'c) -> 'c) -> ('d -> 'e) -> ('f -> 'f) -> 'g) -> ((('a -> 'b) -> ('b -> 'c) -> 'c) -> ('d -> 'e) -> ('f -> 'f) -> 'g) -> (('a -> 'b) -> ('b -> 'c) -> 'c) -> ('d -> 'e) -> ('f -> 'f) -> 'g'    
The types ''a' and '('a -> 'b) -> ('b -> 'c) -> 'c' cannot be unified"

Я застрял, что я делаю не так? И я также буду признателен за любые предложения по улучшению моего кода.

...