带折叠的地图查找功能
Map lookup function with fold
我想使用折叠创建一个 "map lookup" 函数。
这是我的"map"(只是一个元组列表):
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)
但是,这不会编译,它会产生 "cannot construct infinite type" 错误。
你能给我解释一下为什么这是错误的吗?我该如何让它发挥作用?
请注意,我知道 Data.Map 及其导出的地图函数,我想这样做只是为了了解折叠的工作原理。
首先这是一个工作版本——我会在几分钟后回来解释:
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
所以你的元素和结果需要相同的类型 - 但在这里你想要值作为结果但是折叠 [=46= 的元组].
- 这就是我切换到更通用的
foldl
的原因(请注意,我对这是否是正确的选择不感兴趣 - 请参阅 foldl'
vs foldl
vs foldr
)
- 这个函数永远不可能是完整的(如果键不在 dictionary/key-value-pair-list 中)所以我选择在结果类型中反映这一点,现在是
Maybe v
- 当然这样就可以了很容易找到一个初始值:Nothing
如果您不喜欢 Maybe
部分,您也可以使用 error
代替:
lookUp :: (Eq k) => k -> [(k,v)] -> v
lookUp k = foldl (\ acc (k',v) -> if k == k' then v else acc) (error "key not found")
备注:
这不是最有效的实施方式,因为无论您是否找到了密钥,您都将浏览所有列表 - 请随意尝试想出一些可以做到的事情
提示: Haskell 是懒惰的 - 也许你可以通过过滤掉正确的 key/value-pairs 找到一些东西,取这个的安全头然后映射到值部分 ;) )
我想使用折叠创建一个 "map lookup" 函数。
这是我的"map"(只是一个元组列表):
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)
但是,这不会编译,它会产生 "cannot construct infinite type" 错误。
你能给我解释一下为什么这是错误的吗?我该如何让它发挥作用?
请注意,我知道 Data.Map 及其导出的地图函数,我想这样做只是为了了解折叠的工作原理。
首先这是一个工作版本——我会在几分钟后回来解释:
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
所以你的元素和结果需要相同的类型 - 但在这里你想要值作为结果但是折叠 [=46= 的元组]. - 这就是我切换到更通用的
foldl
的原因(请注意,我对这是否是正确的选择不感兴趣 - 请参阅foldl'
vsfoldl
vsfoldr
) - 这个函数永远不可能是完整的(如果键不在 dictionary/key-value-pair-list 中)所以我选择在结果类型中反映这一点,现在是
Maybe v
- 当然这样就可以了很容易找到一个初始值:Nothing
如果您不喜欢 Maybe
部分,您也可以使用 error
代替:
lookUp :: (Eq k) => k -> [(k,v)] -> v
lookUp k = foldl (\ acc (k',v) -> if k == k' then v else acc) (error "key not found")
备注:
这不是最有效的实施方式,因为无论您是否找到了密钥,您都将浏览所有列表 - 请随意尝试想出一些可以做到的事情
提示: Haskell 是懒惰的 - 也许你可以通过过滤掉正确的 key/value-pairs 找到一些东西,取这个的安全头然后映射到值部分 ;) )