无法使用 zip 链接 Map.fromList

Cannot chain Map.fromList with zip

在 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
    

    当然你可以“撤销 uncurrying”

    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
    

    我不喜欢这两个。

  • 只需提出至少一个参数point-ful。

    f keys = Map.fromList . zip keys
    

    这就是我的建议。