Home > Enterprise >  Cannot chain Map.fromList with zip
Cannot chain Map.fromList with zip

Time:03-10

executing the following Code in ghci:

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

will give the following error:

<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)

I would have expected f to a function of type [a] -> [b] -> Map a b What's happening?

CodePudding user response:

If you compose zip with another function it means you're considering it as a function

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

So the function you compose it with would need to have an argument of type [b] -> [(a,b)]. But the argument of Map.fromList is only the [(a,b)] part, i.e. it requires that the other argument also has been applied already.

There are a couple of ways around this:

  • Use the function in uncurried form. That has the behaviour you seem to have expected here – i.e., Map.fromList . uncurry zip typechecks – however it means the whole thing will also take the list arguments in tuple form, which is kind of scorned upon by Haskellers

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

    Of course you could “undo the uncurrying”

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

    but that's a bit silly.

  • Do the composition with the version of fromList that composes itself after another argument. This can be done as an operator section of the composition operator:

    f = (Map.fromList . ) . zip
    

    The same thing can also be achieved by tapping into the Functor (c->) instance

    f = fmap Map.fromList . zip
    

    I'm not a fan of either of these.

  • Simply make at least one of the arguments point-ful.

    f keys = Map.fromList . zip keys
    

    That's what I would recommend.

  • Related