另一个 Haskell 教程/勘误
Haskell | |
---|---|
另一个 Haskell 教程 | |
前言 | |
简介 | |
入门 | |
语言基础 (解决方案) | |
类型基础 (解决方案) | |
IO (解决方案) | |
模块 (解决方案) | |
高级语言 (解决方案) | |
高级类型 (解决方案) | |
单子 (解决方案) | |
高级 IO | |
递归 | |
复杂度 | |
此页面包含迄今为止在 YAHT 的 PDF 版本 中发现的勘误列表(其中一些可能已经在 在线 HTML 版本 中更正 - (导入))。
- 练习 3.1:“我们已经看到乘法比除法绑定得更紧密。” - 就我而言,乘法和除法具有相同的优先级,因此它们绑定得同样紧密。也许你的意思是加法与乘法或乘法与幂?我看到它已经在在线版本中修复了。
- 练习 7.1 的解决方案在第 79 页的“7.3 部分应用”下存在错误(请参阅 高级语言:部分应用,以获取已更正的相应 HTML 版本),练习陈述如下
练习 |
---|
如果可能,将以下函数转换为无点风格。 [...] func5 f l = foldr (\x y -> f (y,x)) 0 l |
- 第 81 页的文本指出
“我们创建一个值,称之为 x,它的值为 Red。然后我们将其应用于 colorToRGB。我们检查是否可以将 x 与 Red “匹配”。此匹配失败,因为根据 Eq Color 的定义,Red 不等于 Yellow。”
显然,前提是错误的,初始值 x 应该是 'Yellow',以便段落的其余部分有意义。
- 根据 PDF 文件 的第 172 页,解决方案陈述如下
[...] func5 = foldr (uncurry $ flip f) 0
但是,正如 Michael Mossey 在 Haskell-Beginners 邮件列表中 指出的那样,该解决方案实际上是错误的。
这是正确的解决方案
[...] func5 = flip foldr 0 . flip . curry
作为旁注,Daniel Fischer 已 提供 了使用类型验证解决方案正确性的简洁方法,如下所示
检查结果是否正常的一种简单方法是
示例
Prelude> :t flip foldr 0 . flip. curry flip foldr 0 . flip. curry :: (Num c) => ((c, b) -> c) -> [b] -> c Prelude> :t \f list -> foldr (\x y -> f (y,x)) 0 list \f list -> foldr (\x y -> f (y,x)) 0 list :: (Num b) => ((b, a) -> b) -> [a] -> b Prelude> :t \f -> foldr (uncurry $ flip f) 0 \f -> foldr (uncurry $ flip f) 0 :: (Num b1) => (b -> a -> b1 -> b1) -> [(a, b)] -> b1
因此,您会看到您的结果具有正确的类型,而 Hal 的结果没有。
在上述描述中,前两行中的第一对显示了
flip foldr 0 . flip. curry
(即,要验证的解决方案)的类型是
(Num c) => ((c, b) -> c) -> [b] -> c
第二对两行显示了
\f list -> foldr (\x y -> f (y,x)) 0 list
(即,本质上是练习中给出的表达式,即 f l = foldr (\x y -> f (y,x)) 0 l
)的类型也是
(Num b) => ((b, a) -> b) -> [a] -> b
(请注意,这与上面的类型相同,只是使用重命名变量编写。)
第三对两行显示了
\f -> foldr (uncurry $ flip f) 0
(即,Hal 在教程的 PDF 版本 中给出的解决方案)的类型是
(Num b1) => (b -> a -> b1 -> b1) -> [(a, b)] -> b1
这是一个不同的类型。因此,Hal 给出的解决方案是错误的。
注意
(感谢 Michael Mossey 和 Daniel Fischer 在 Haskell-Beginners 邮件列表中就这个问题进行的讨论。)
-- Benjamin L. Russell
2. 练习 4.11
练习 |
---|
4.11. 测试 CPS 风格的 fold 是否模拟 foldr 或 foldl 中的任何一个。如果不是,区别在哪里? |
它没有指定“CPS 风格的 fold”函数,因此读者应该假设练习是关于先前定义的 cfold
cfold’ f z [] = z cfold’ f z (x:xs) = f x z (\y -> cfold’ f y xs) cfold f z l = cfold’ (\x t g -> f x (g t)) z l
但 YAHT 中给出的解决方案实际上不是关于这个函数。事实上,这个函数的行为与 foldr 完全一样。该解决方案是关于一个非常相似的函数:唯一的区别是 cfold' 的第二个情况中参数的顺序,即
cfold' f z (x:xs) = f z x (\y -> cfold' f y xs)
YAHT 从未经过全面校对,因此这只是一个部分列表。 |
这仍在进行中。请随时根据需要进行添加! |