Haskell-使用foldr编写映射函数

时间:2015-05-07 14:38:38

标签: haskell

我正在尝试使用foldr编写map函数。问题是当我运行这段代码时:

> myMap f xs = foldr (\ acc x -> acc :(f x)) [] xs

我有以下问题:

  

使用'它没有(Num [a0])的实例'

但是当我跑步时

myMap f xs = foldr (\x acc-> (f x):acc) [] xs

完美无缺。有什么想法吗?

2 个答案:

答案 0 :(得分:5)

您发布的错误并非来自您对myMap的定义,而是来自您如何使用它。第一个myMap的类型为([a] -> [a]) -> [a] -> [a],与Prelude.map的类型不匹配。在第二个中,您已经交换了变量名称以及您应用f的变量名称。编译器并不关心您将lambda中的参数命名为foldr,因此foldr (\x acc -> f x : acc)foldr (\foo bar -> f foo : bar)相同。这可能是你在这里绊倒的。

第二个起作用是因为(简单地说)它是正确的。首先,您将f应用于累加器列表x(即使您有一个名为acc的变量,它不是您的累加器),所以{{1必须获取一个列表并返回一个列表。在第二步中,您将f应用于每个元素,然后将其添加到累加器列表中。如果您有f,则其类型为

myMap (+1)

其中说你必须传递一个值列表myMap (+1) :: Num [a] => [a] -> [a] ,其中[a]实现[a],目前没有Num的实例,也不会有

TL; DR:在第一个中,您将映射函数应用于累加器列表,在第二个中,您将映射函数应用于每个元素。

答案 1 :(得分:5)

折叠器的类型是

private void InvalidateCache(string id)
        {
            var urlToRemove = Url.Action("myAction", "myController", new { id});
            //this will always clear the cache as the route config will create the path
            Response.RemoveOutputCacheItem(urlToRemove);
            Response.RemoveOutputCacheItem(string.Format("/myController/myAction/{0}", id));
            Response.RemoveOutputCacheItem(string.Format("/u/0/myController/myAction/{0}", id));
        }

因此,foldr用于遍历和累积列表的二进制操作 类型为foldr :: (a -> b -> b) -> b -> [a] -> b ,它首先取一个列表元素(类型(a -> b -> b)),然后取累加器(类型a),得到类型为b的表达式。

所以,你的第一个myMap函数不起作用,因为你正在使用" acc"和" x"以相反的顺序。 您想将b应用于x,然后将其附加到f类型的累积器(在这种情况下为列表)