无法使用zip链接Map.fromList



在ghci中执行以下代码:

import qualified Data.Map.Strict as Map
f = Map.fromList . zip

将给出以下错误:

<interactive>:16:20: error:
• Couldn't match type ‘[b0] -> [(a, b0)]’ with ‘[(k, a1)]’
Expected type: [a] -> [(k, a1)]
Actual type: [a] -> [b0] -> [(a, b0)]
• Probable cause: ‘zip’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘zip’
In the expression: Map.fromList . zip
In an equation for ‘f’: f = Map.fromList . zip
• Relevant bindings include
f :: [a] -> Map.Map k a1 (bound at <interactive>:16:1)

我本来希望f是[a] -> [b] -> Map a b类型的函数发生了什么事?

如果您用另一个函数组合zip,则意味着您将其视为一个函数

zip::[a]->([b]->[(a,b(](

所以组成它的函数需要有一个类型为[b] -> [(a,b)]的参数。但Map.fromList的自变量只是[(a,b)]的一部分,即它要求其他自变量也已经应用。

有几种方法可以解决这个问题:

  • 以未压缩的形式使用函数。这具有您在这里所期望的行为,即Map.fromList . uncurry zip类型检查,但这意味着整个过程也将采用元组形式的列表参数,这有点被Haskellers 蔑视

    f :: Ord a => ([a], [b]) -> Map.Map a b
    f = Map.fromList . uncurry zip
    

    当然,你可以"撤销">

    f :: Ord a => [a] -> [b] -> Map.Map a b
    f = curry $ Map.fromList . uncurry zip
    

    但这有点傻。

  • 使用fromList的版本进行组合,该版本在另一个参数之后进行组合。这可以作为合成操作符的操作符部分来完成:

    f = (Map.fromList . ) . zip
    

    同样的事情也可以通过利用Functor (c->)实例来实现

    f = fmap Map.fromList . zip
    

    我不喜欢这两种。

  • 只需让至少一个论点有针对性。

    f keys = Map.fromList . zip keys
    

    这就是我的建议。

最新更新