从lambda到函数式编程

时间:2023-03-09 22:42:48
从lambda到函数式编程
 Object.send(:remove_const,'TRUE')
Object.send(:remove_const,'FALSE') def to_integer(pro)
pro[-> n { n + 1 }][0]
end def to_boolean(pro)
pro[true][false]
end def to_array(l, count = nil)
array = []
until to_boolean(IS_EMPTY[l]) || count == 0
array.push FIRST[l]
l = REST[l]
count = count - 1 unless count.nil?
end
array
end def array_map_to_integer(my_list, count = nil)
to_array(my_list, count).map{ |p| to_integer(p) }
end def to_char(c)
to_integer(c).chr
end def to_string(s)
to_array(s).map{ |c| to_char(c) }.join
end def puts_strings(strs)
to_array(strs).each do |p|
puts to_string(p)
end
nil
end ZERO = -> p { -> x { x } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }
THREE = -> p { -> x { p[p[p[x]]] } } FIVE = -> p { -> x { p[p[p[p[p[x]]]]] } } FIFTEEN = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }
HUNDRED = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } } TRUE = -> x { -> y { x } }
FALSE = -> x { -> y { y } } IF = -> b { b } IS_ZERO = -> n { n[-> x { FALSE }][TRUE] } PAIR = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] } INC = -> n { -> p { -> x { p[n[p][x]] } } } SLIDE = -> p { PAIR[RIGHT[p]][INC[RIGHT[p]]] }
DEC = -> n { LEFT[n[SLIDE][PAIR[ZERO][ZERO]]] } ADD = -> m { -> n { n[INC][m] } }
SUB = -> m { -> n { n[DEC][m] } }
MUL = -> m { -> n { n[ADD[m]][ZERO] } }
POW = -> m { -> n { n[MUL[m]][ONE] } } IS_LESS_OR_EQUAL =
-> m { -> n { IS_ZERO[SUB[m][n]] } } Z = -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }
MOD = Z[-> f { -> m { -> n {
IF[IS_LESS_OR_EQUAL[n][m]][
-> x {
f[SUB[m][n]][n][x]
}
][
m
]
} } }] DIV = Z[-> f { -> m { -> n {
IF[IS_LESS_OR_EQUAL[n][m]][
-> x {
INC[f[SUB[m][n]][n]][x]
}
][
ZERO
]
} } } ] EMPTY = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY= LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] } PUSH = -> l { -> x {
FOLD[l][UNSHIFT[EMPTY][x]][UNSHIFT]
} } RANGE = Z[-> f {
-> m { -> n {
IF[IS_LESS_OR_EQUAL[m][n]][
-> x {
UNSHIFT[f[INC[m]][n]][m][x]
}
][
EMPTY
]
} }
}]
FOLD = Z[-> f {
-> l { -> x { -> g {
IF[IS_EMPTY[l]][
x
][
-> y {
g[f[REST[l]][x][g]][FIRST[l]][y]
}
]
} } }
}] MAP = -> k { -> f {
FOLD[k][EMPTY][
-> l { -> x { UNSHIFT[l][f[x]] } }
]
} } TEN = MUL[TWO][FIVE]
ASC_48 = MUL[MUL[THREE][INC[THREE]]][INC[THREE]]
ASC_65 = ADD[MUL[ADD[FIVE][ONE]][TEN]][FIVE]
CHAR_B = INC[ASC_65]
CHAR_F = ADD[ASC_65][FIVE]
CHAR_I = ADD[CHAR_F][THREE]
CHAR_U = ADD[CHAR_I][MUL[THREE][INC[THREE]]]
CHAR_Z = ADD[CHAR_U][FIVE] FIZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][CHAR_Z]][CHAR_Z]][CHAR_I]][CHAR_F]
BUZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][CHAR_Z]][CHAR_Z]][CHAR_U]][CHAR_B]
FIZZBUZZ= UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[BUZZ][CHAR_Z]][CHAR_Z]][CHAR_I]][CHAR_F] TO_DIGITS=
Z[-> f { -> n { PUSH[
IF[IS_LESS_OR_EQUAL[n][DEC[TEN]]][
EMPTY
][
-> x {
f[DIV[n][TEN]][x]
}
]
][ADD[MOD[n][TEN]][ASC_48]] } } ] SOLUTION=
MAP[RANGE[ONE][HUNDRED]][-> n {
IF[IS_ZERO[MOD[n][FIFTEEN]]][
FIZZBUZZ
][IF[IS_ZERO[MOD[n][THREE]]][
FIZZ
][IF[IS_ZERO[MOD[n][FIVE]]][
BUZZ
][
TO_DIGITS[n]
]]]
} ] ZEROS = Z[-> f { UNSHIFT[f][ZERO] }]
UPWARDS_OF = Z[-> f { -> n { UNSHIFT[-> x { f[INC[n]][x] }][n] } }]
MULTIPLES_OF =
-> m {
Z[-> f {
-> n { UNSHIFT[-> x { f[ADD[m][n]][x] }][n] }
}][m]
}
MULTIPLY_STREAMS =
Z[-> f {
-> k { -> l {
UNSHIFT[-> x { f[REST[k]][REST[l]][x] }][MUL[FIRST[k]][FIRST[l]]]
} }
}]

在λ演算中,每个表达式都代表一个函数,这个函数有一个参数,并且返回一个值。不论是参数和返回值,也都是一个单参的函数。可以这么说,λ演算中,只有一种“类型”,那就是这种单参函数。

在lambda演算中有许多方式都可以定义自然数,但最常见的还是邱奇数。

ZERO    = -> p { -> x {       x    } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }
THREE = -> p { -> x { p[p[p[x]]] } } FIVE = -> p { -> x { p[p[p[p[p[x]]]]] } } FIFTEEN = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }
HUNDRED = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }

以此类推。直观地说,lambda演算中的数字n就是一个把函数f作为参数并以f的n次幂为返回值的函数。换句话说,邱奇整数是一个高阶函数 -- 以单一参数函数f为参数,返回另一个单一参数的函数。

习惯上,下述两个定义(称为邱奇布尔值)被用作TRUE和FALSE这样的布尔值:

TRUE    = -> x { -> y { x } }
FALSE = -> x { -> y { y } }

“谓词”是指返回布尔值的函数。最基本的一个谓词是ISZERO,当且仅当其参数为零时返回真,否则返回假:

IS_ZERO = -> n { n[-> x { FALSE }][TRUE] }

运用谓词与上述TRUE和FALSE的定义,使得"if-then-else"这类语句很容易用lambda演算写出。

有序对(2-元组)数据类型可以用TRUE、FALSE和IF来定义。

PAIR    = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] }

链表数据类型可以定义为,要么是为空列表保留的值(e.g.FALSE),要么是CONS一个元素和一个更小的列表。

EMPTY   = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY= LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] }

递归是使用函数自身的函数定义;在表面上,lambda演算不允许这样。但是这种印象是误解。

使用Y组合子和Z组合子实现可以递归:

Z       = -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }