我正在尝试使用foldr编写map函数。问题是当我运行这段代码时:
> myMap f xs = foldr (\ acc x -> acc :(f x)) [] xs
我有以下问题:
使用'它没有(Num [a0])的实例'
但是当我跑步时
myMap f xs = foldr (\x acc-> (f x):acc) [] xs
完美无缺。有什么想法吗?
答案 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
类型的累积器(在这种情况下为列表)