另一個 Haskell 教程/勘誤
| Haskell | |
|---|---|
| |
| 另一個 Haskell 教程 | |
| 前言 | |
| 簡介 | |
| 入門 | |
| 語言基礎 (解答) | |
| 型別基礎 (解答) | |
| IO (解答) | |
| 模組 (解答) | |
| 高階語言 (解答) | |
| 高階型別 (解答) | |
| 單子 (解答) | |
| 高階 IO | |
| 遞迴 | |
| 複雜度 | |
此頁面包含一個錯誤列表,這些錯誤是在 YAHT 的 PDF 版本 中發現的(其中一些可能已經在 線上 HTML 版本 中修正了 - (匯入)).
- 練習 3.1:"我們已經看到乘法比除法結合得更緊密。" - 就我而言,乘法和除法具有相同的優先順序,因此它們的結合程度相同。也許你指的是加法與乘法或乘法與乘方?我看到它已經在線上版本中修正了。
- 練習 7.1 的解答(第 79 頁,在“7.3 部分應用”下)存在一個 bug,練習內容如下(參見 高階語言:部分應用 獲取對應的 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 從未經過全面校對,因此這只是一個部分列表。 |
這仍然是一個正在進行的工作。請隨時根據需要新增內容! |
