【发布时间】:2017-11-05 23:32:37
【问题描述】:
我已经看过 John Hughes 题为 Why Functional Programming Matters 的精彩演讲几次,直到最近才决定实际尝试实现布尔值、整数,当然还有阶乘的“极简”版本,如 video 所示.
我实现了true、false、ifte、zero、one、two、iszero、decr,最后是facthere,如下所示:
-- boolean
true x y = x
false x y = y
ifte bool t e = bool t e
-- positive integers
three f x = f $ f $ f x
two f x = f $ f x
one f x = f x
zero f x = x
-- add and multiplication
add m n f x = m f $ n f x
mul m n f x = m (n f) x
-- is zero check
iszero n = n (\_ -> false) true
-- decrement
decr n =
n (\m f x -> f (m f zero))
zero
(\x->x)
zero
-- factorial
fact n =
ifte (iszero n)
one
(mul n (fact (decr n)))
问题
我测试了每个函数,除了decr 和fact 之外,它们都可以完美地编译和工作。
尽管 John Hughes 在 6:37 承诺他的 decr 实现有效,但它无法编译并出现以下错误:
错误:变量不在范围内:incr
我不确定incr 应该如何在(\m f x -> f (m incr zero)) 中实现。
现在,如果我将它们定义为 incr = (+1) 并将 decr 的定义更改为以下内容,那么 decr 可以编译并正常工作,但 fact 仍然会导致编译失败。
decr n =
n (\m f x -> f (m incr x))
zero
(\x->x)
zero'
decr 的定义中使用的 lambda (\m f x -> f (m incr zero)) 是否存在错误,或者是否应该以不同的方式定义 incr?
更新
当我将incr 定义为incr n = (\f x -> f (n f x)) 时,decr n 工作正常,但fact n 无法编译。这是错误消息的可读部分:
factorial.hs:30:1: 错误: • 发生检查:无法构造无限类型:
...
|事实 n =
| ^^^^^^^^......
factorial.hs:33:6: 错误: • 发生检查:无法构造无限类型:
...
• In the third argument of ‘ifte’, namely ‘(mul n (fact (decr n)))’ In the expression: ifte (iszero n) one (mul n (fact (decr n))) In an equation for ‘fact’: fact n = ifte (iszero n) one (mul n (fact (decr n)))...
| (mul n (fact (decr n)))
| ^^^^^^^^^^^^^^^^^^^^^
注意:完整的错误信息长达几页。
【问题讨论】:
-
"Variable not in scope:incr" 是因为你还没有实现
incr,但这真的很简单:增加其中一个数字!不是整数+1增量,而是那个教堂编码。 -
请包含足够的代码来重现问题在问题本身中(注意不是在场外资源)。
-
哇,这看起来很有趣。不确定它是否是编译器中的错误......
-
@Bergi 我使用最新版本的 GHC(安装在我的系统上)编译它,但编译失败。我用错误消息的某些部分更新了问题。 (错误信息很长)
-
@Bergi,这绝对不是编译器中的错误。问题是
fact有一个rank-2 类型,所以它需要一个类型签名:fact :: (forall a. (a -> a) -> a -> a) -> (t -> t) -> t -> t。另外,decr的定义是完全错误的;它有一个令人惊讶的类型并计算出错误的结果。
标签: haskell lambda functional-programming factorial