使用foldl而不是foldr和expr定义map

时间:2013-12-15 19:26:45

标签: haskell

我是这样做的 - 但它不起作用:

ma f []       = []
ma f (xs)   = foldl (\y ys -> ys++(f y)) [] xs

foldl :: (a -> b -> a) -> a -> [b] -> a
foldr :: (a -> b -> b) -> b -> [a] -> b

为什么折叠所需的功能有所不同。我的意思是,(a -> b -> a)(a -> b -> b)? 是否可以使用map来定义foldl

我有另一个问题 我有一个expr。

map (:) 

我想知道它会做什么。我试着测试它,但我只得到错误。

type is map (:) :: [a] -> [[a] -> [a]]

我尝试发送[1,2,3]

列表

3 个答案:

答案 0 :(得分:3)

如果您希望它适用于无限列表和有限列表,那就不是了。 head $ map id (cycle [1])必须返回1.

foldl在无限列表上发散(永不停止),因为foldl是递归的。例如,

foldl g z [a,b,c] = g (g (g z a) b) c

g有机会忽略其参数之前,foldl必须到达输入列表的最后一个元素,才能构建对g的第一次调用。无限列表中没有最后一个元素。


至于你的问题,这里是GHCi成绩单,显示map (:)是一个函数,map (:) [1,2,3]是一个函数列表,而GHCi只是没有知道如何Show函数:

Prelude> map (:)
<interactive>:1:0:
    No instance for (Show ([a] -> [[a] -> [a]]))

Prelude> :t map (:)
map (:) :: [a] -> [[a] -> [a]]

Prelude> map (:) [1,2,3]
<interactive>:1:0:
    No instance for (Show ([a] -> [a]))

Prelude> :t map (:) [1,2,3]
map (:) [1,2,3] :: (Num a) => [[a] -> [a]]

Prelude> map ($ [4]) $ map (:) [1,2,3]
[[1,4],[2,4],[3,4]]

Prelude> foldr ($) [4] $ map (:) [1,2,3]
[1,2,3,4]

答案 1 :(得分:0)

当您在其中一个函数中交换类型变量名称时,它变得更加明显:

foldl :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b

...因为毕竟我们需要的是结果,即[a] -> b。或者,更具体地说,[a] -> [b],所以我们也可以替换

foldl :: ([b] -> a -> [b]) -> [b] -> [a] -> [b]
foldr :: (a -> [b] -> [b]) -> [b] -> [a] -> [b]

在每个签名中只留下一个非列表项,即a。这就是我们可以应用f的原因,因此,在foldl的情况下,它必须是lambda的 2nd 参数:

foldl (\ys y -> ys ++ f y)

正如Xeo评论的那样,这还没有完成,因为f y的类型为b,而不是[b]。我想你可以弄清楚如何解决这个问题......

答案 2 :(得分:0)

ma f []       = []
ma f (xs)   = foldl (\ys y -> ys++[(f y)]) [] xs

工作,但为什么arg对lambda的顺序很重要。 ma f (xs) = foldl (\y ys -> ys++[(f y)]) [] xs出错