应用等式推理1和抽象。你有
one f x = f x -- :: (a -> b) -> a -> b
two f x = f (f x) -- = f (one f x) -- :: (a -> a) -> a -> a
three f x = f (f (f x)) -- = f (two f x) -- :: (a -> a) -> a -> a
-- ~~~~~~~~~~~
因此,自然定义了后继函数next
,因此three = next two
. 是的,它就像写next two
而不是three
上面的等式一样简单:
next :: ((b -> c) -> a -> b) -> (b -> c) -> a -> c
-- three f x = next two f x = f (two f x) -- `two` is a formal parameter
-- ~~~~~~~~~~~
next num f x = f (num f x) -- generic name `num`
zero :: t -> a -> a
zero f x = x
这捕捉到了继承的模式。f
将用作后继函数,并x
用作零值。其余的紧随其后。例如,
plus :: (t -> b -> c) -> (t -> a -> b) -> t -> a -> c
plus two one f x = two f (one f x) -- formal parameters two, one
-- = f (f (one f x)) -- an example substitution
-- = f (f (f x) -- uses the global definitions
-- = three f x -- for one, two, three
ie将被(而不是“通常” )one f x
用作零值,因此表示. “数字”表示连续的n 个操作。two
x
three
n
+1
同样,上面实际上定义了一般plus
操作,因为two
和one
只是两个形式函数参数:
Prelude> plus three two succ 0 -- built-in `succ :: Enum a => a -> a`
5
Prelude> :t plus three two
plus three two :: (a -> a) -> a -> a
Prelude> plus three two (1:) [0]
[1,1,1,1,1,0]
这里要喘口气的关键是,函数是一个在调用时会产生值的对象。它本身就是一个不透明的物体。我们应用于它的“观察者”参数,为它提供了“意义”,它意味着什么是零,或者找到一个后继者,从而定义当我们观察一个数字的值时会产生什么结果。
1即在任何表达式中用定义的 RHS 自由替换 LHS,或者用 LHS 替换 RHS,如您认为合适的(直到变量重命名,当然,不捕获/隐藏现有的自由变量)。