我遇到了一个Haskell基础问题:折叠+匿名函数
我正在使用foldl
开发bin2dec程序
解决方案如下所示:
bin2dec :: String -> Int
bin2dec = foldl (\x y -> if y=='1' then x*2 + 1 else x*2) 0
我理解foldl
/ foldr
的基本概念,但我无法理解x y
代表的参数。
答案 0 :(得分:7)
查看foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
考虑foldl f z list
所以foldl基本上在列表上递增(或任何可折叠的),从左边取1个元素并应用f z element
以获得新元素用于下一步,同时折叠其余元素。基本上,foldl的一个简单定义可能有助于理解它。
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
来自Haskell wiki的图表可能有助于建立更好的直觉。
考虑您的函数f = (\x y -> if y=='1' then x*2 + 1 else x*2)
并尝试为foldl f 0 "11"
编写跟踪。此处"11"
与['1','1']
foldl f 0 ['1','1']
= foldl f (f 0 '1') ['1']
现在f是一个带有2个参数的函数,第一个是整数,第二个是一个字符并返回一个整数。
所以在这种情况下x=0
和y='1'
,f x y = 0*2 + 1 = 1
= foldl f 1 ['1']
= foldl f (f 1 '1') []
现在再次应用f 1 '1'
。这里x=1
和y='1'
f x y = 1*2 + 1 = 3
。
= foldl f 3 []
将foldl
的第一个定义用于空列表。
= 3
“11”的十进制表示形式。
答案 1 :(得分:2)
使用类型!您可以在GHCi中键入:t
,然后输入任何函数或值以查看其类型。如果我们询问foldl
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
输入列表的类型为[b]
,因此它是b
的列表。输出类型为a
,这是我们要生成的。您还必须为折叠提供初始值,同样为a
类型。该函数的类型为
a -> b -> a
第一个参数(a
)是到目前为止计算的折叠值。第二个参数(b
)是列表的下一个元素。所以在你的例子中
\x y -> if y == '1' then x * 2 + 1 else x * 2
参数x
是您目前已计算的二进制数,y
是列表中的下一个字符('1'
或'0'
)