如何解决重新实现 Map.fromListWith 函数
我一直在尝试在 Haskell 中重新实现 Map.fromListWith
函数,但遇到了一个我不明白的错误。
这是我的实现:
fromListWith_ :: (a -> a -> a) -> [(k,a)] -> Map.Map k a
fromListWith_ fn = foldl foldfn Map.empty
where
foldfn :: (Map.Map k a) -> (k,a) -> Map.Map k a
foldfn m (key,val) = Map.insertWith fn key val m
这是我的错误:
Lecture8.hs:33:49: error:
• Couldn't match expected type 'a' with actual type 'a1'
'a1' is a rigid type variable bound by
the type signature for:
foldfn :: forall k1 a1. Map.Map k1 a1 -> (k1,a1) -> Map.Map k1 a1
at src/Lecture8.hs:32:15
'a' is a rigid type variable bound by
the type signature for:
fromListWith_ :: forall a k.
(a -> a -> a) -> [(k,a)] -> Map.Map k a
at src/Lecture8.hs:29:18
• In the third argument of 'Map.insertWith',namely 'val'
In the expression: Map.insertWith fn key val m
In an equation for 'foldfn':
foldfn m (key,val) = Map.insertWith fn key val m
• Relevant bindings include
val :: a1 (bound at src/Lecture8.hs:33:20)
m :: Map.Map k1 a1 (bound at src/Lecture8.hs:33:12)
foldfn :: Map.Map k1 a1 -> (k1,a1) -> Map.Map k1 a1
(bound at src/Lecture8.hs:33:5)
fn :: a -> a -> a (bound at src/Lecture8.hs:30:15)
fromListWith_ :: (a -> a -> a) -> [(k,a)] -> Map.Map k a
(bound at src/Lecture8.hs:30:1)
我尝试从 foldfn
中删除类型注释,这会产生不同的错误:
Lecture8.hs:32:26: error:
• No instance for (Ord k) arising from a use of ‘foldfn’
Possible fix:
add (Ord k) to the context of
the type signature for:
fromListWith_ :: (a -> a -> a) -> [(k,a)] -> Map.Map k a
• In the first argument of ‘foldl’,namely ‘foldfn’
In the expression: foldl foldfn Map.empty
In an equation for ‘fromListWith_’:
fromListWith_ fn
= foldl foldfn Map.empty
where
foldfn m (key,val) = Map.insertWith fn key val m
非常感谢任何帮助。
解决方法
我认为您的实现一切正常 - 不过您需要 ScopedTypeVariables
来处理内部函数的类型:
{-# LANGUAGE ScopedTypeVariables #-}
fromListWith_ :: forall a k. Ord k => (a -> a -> a) -> [(k,a)] -> Map.Map k a
fromListWith_ fn = foldl foldfn Map.empty
where
foldfn :: Map.Map k a -> (k,a) -> Map.Map k a
foldfn m (key,val) = Map.insertWith fn key val m
如果没有那些 范围 变量,a
中的 foldfn :: (Map.Map k a) -> (k,a) -> Map.Map k a
被假定为不同的类型变量(有点像 shadowing) - 与k
当然。
注意:要完成这项工作,您还需要显式 forall
!
如果你不喜欢这个,只需删除签名:
fromListWith_ :: Ord k => (a -> a -> a) -> [(k,a)] -> Map.Map k a
fromListWith_ fn = foldl foldfn Map.empty
where
foldfn m (key,val) = Map.insertWith fn key val m
PS:您也缺少 Ord k
约束。
insertWith
包含此约束,因此您需要传播它。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。