通过任务,我们必须通过 foldr 实现 foldl。通过比较函数签名和 foldl 实现,我得到了以下解决方案:
myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl _ acc [] = acc
myFoldl fn acc (x:xs) = foldr fn' (fn' x acc) xs
where
fn' = flip fn
只需翻转函数参数以满足 foldr 预期类型并通过递归应用传递的函数来模拟 foldl 定义。这是一个惊喜,因为我的老师给这个答案评分为零分。
我什至检查了这个定义以与标准 foldl 相同的方式堆叠其中间结果:
> myFoldl (\a elm -> concat ["(",a,"+",elm,")"]) "" (map show [1..10])
> "((((((((((+1)+10)+9)+8)+7)+6)+5)+4)+3)+2)"
> foldl (\a elm -> concat ["(",a,"+",elm,")"]) "" (map show [1..10])
> "((((((((((+1)+10)+9)+8)+7)+6)+5)+4)+3)+2)"
正确答案是以下定义:
myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl f z xs = foldr step id xs z
where step x g a = g (f a x)
只是问为什么我以前的定义不正确?