重新实现 Map.fromListWith 函数
Reimplementing Map.fromListWith function
我一直在尝试在 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
没有那些 scoped 变量 foldfn :: (Map.Map k a) -> (k, a) -> Map.Map k a
中的 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
包含此约束,因此您需要传播它。
我一直在尝试在 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
没有那些 scoped 变量 foldfn :: (Map.Map k a) -> (k, a) -> Map.Map k a
中的 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
包含此约束,因此您需要传播它。