带折叠的地图查找功能

时间:2015-07-20 18:42:57

标签: haskell fold

我想创建一个"地图查找"功能使用折叠。

这是我的地图" (只是一个元组列表):

phoneBook:: [([Char], [Char])]
phoneBook = [("bob", "00-21-55")
            ,("jack", "55-51-55")
            ,("joe", "10-61-25")
            ,("susy", "06-21-55")
            ,("clara", "50-31-95")
            ]

这就是我想写的功能:

lookUp :: (Eq k) => k -> [(k,v)] -> v
lookUp k = foldl1 (\acc (x,y) -> if k == y then y else acc)

然而,这不编译,它产生一个"不能构造无限类型"错误。

你能解释一下为什么这是错误的以及如何让它发挥作用?

请注意,我知道Data.Map及其导出的地图功能,我想这样做只是为了了解折叠是如何工作的。

1 个答案:

答案 0 :(得分:5)

首先是工作版本 - 我会在几分钟后回来解释:

ASP.net MVC

你遇到的问题是:

  • 对于lookUp :: (Eq k) => k -> [(k,v)] -> Maybe v lookUp k = foldl (\ acc (k',v) -> if k == k' then Just v else acc) Nothing ,您的类型为foldl1,因此您的元素和结果需要相同的类型 - 但是在这里您希望将值作为结果,但折叠键/值对的元组。
  • 这就是为什么我切换到更一般的foldl1 :: (a -> a -> a) -> [a] -> a(请注意,如果这是正确的选择,我不感兴趣 - 请参阅foldl vs foldl' vs {{1} })
  • 这个函数永远不会是完全的(如果键不在词典/键值对列表中)所以我选择在结果类型中反映这个,现在是foldl - 当然这个这样可以很容易地找到初始值:foldr

如果你不喜欢Maybe v部分,你可以使用Nothing而不是这样:

Maybe

说明:

这不是最有效的实现,因为无论你是否找到了密钥,你都会仔细查看所有列表 - 随意尝试提出一些可以做到的事情

提示:Haskell是懒惰的 - 也许你可以通过过滤掉正确的键/值对来找到一些东西,拿出这个的安全头然后maping到值部分;))