[英]Why does foldr work on infinite lists in Haskell but foldl doesn't?
[英]Haskell foldr results in type error while foldl doesn't
我正在通過“從第一原理開始的Haskell編程”。 在“折疊列表”一章中,練習5f,
當我評估
foldr const 'a' [1..5]
我懂了
沒有(Num Char)實例產生於文字'1'的情況
但是,隨着
foldl const 'a' [1..5]
我得到'a'
。
我得到的褶皺都懶, foldr
不穿過脊椎和foldl
一樣。 但是,即使查看foldr和foldl的定義,
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
我不知道為什么會有這種類型的錯誤。 我猜編譯器根據z
( Char
)的類型推斷x
( Num
)的類型,但是我看不到它在哪里繪制連接,因為const
或f
不需要將其兩個參數設為相同的類型。
有什么想法嗎?
好,看看文件foldr :: (a -> b -> b) -> b -> [a] -> b
的類型foldr :: (a -> b -> b) -> b -> [a] -> b
從右邊開始,你顯然必須有a
是一些實例Num
和Enum
(因為你用[1..5]
接下來,您傳遞'a'
這樣您就有b ~ Char
最后,你有const
的功能-和const是const :: a -> b -> a
-注意你怎么現在必須有a ~ b
,因為你統一
a -> b -> b
a -> b -> a
^^^^^
但這當然意味着'a'
必須是Char
不是的Num
實例的值...這是您的錯誤(它抱怨1,因為從左開始是問題很明顯的地方)
foldl
在另一側具有foldl :: (b -> a -> b) -> b -> [a] -> b
因此,現在您又有a
Num
a
某個實例, b
必須再次為Char
但現在const
就適合了(只需將b
和a
切換為const類型)
foldl
和foldr
用不同順序的參數調用f
。 這是foldr
調用const x 'a'
,但foldl
調用const 'a' x
。 后者的結果為'a',這很好,但是后者的結果為x
,這是錯誤的,因為x
是一個Int
且結果應該與累加器( Char
)具有相同的類型。
這是一個打字問題。 foldl
的類型是
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
文件foldr
類型為:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
當您將foldr
應用於const
時,您將獲得:
foldr const :: Foldable t => b -> t b -> b
接下來,提供'a'
參數,得到
(foldr const 'a') :: Foldable t => t Char -> Char
因此,當您傳遞[1..5]
作為參數時,它將嘗試通過(Enum a, Num a) => [a]
統一t Char
。 Char
類型是Enum
類的實例,但不是Num
的實例,這是您收到此錯誤消息的原因。
就像其他人所說的, foldl
和foldr
中參數的順序是不同的。 使用flip const
代替:
> foldr (flip const) 'a' [1..5]
'a'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.