Search code examples
haskelltypessyntaxtypeclassfunction-composition

Haskell: Compose a function of specific type with one of general type?


I was writing a quick one-liner in GHCi and tried to compose sum with map. I figured the reason it failed is because map gives output of a general type [b] whereas sum takes in specific input Num a => [a]. However, there is nothing wrong with this code assuming that the output of the map function is type Num b => [b].

I thought writing a restricting type declaration might work (although I guess that prevents you from doing it in GHCi) but it still didn't:

myFunc :: Num b => (a -> b) -> [a] -> b
myFunc = sum . map

Gave me the following error:

Couldn't match expected type `[[a] -> b]'
            with actual type `[a] -> [b]'
Expected type: (a -> b) -> [[a] -> b]
  Actual type: (a -> b) -> [a] -> [b]
In the second argument of `(.)', namely `map'
In the expression: sum . map

Is there any way to do this? Maybe I am just missing something obvious (new to Haskell).


Solution

  • sum . map isn't a definition you're looking for. Observe that

     (.) :: (b -> c) -> (a -> b) -> a -> c
    

    The dot operator accepts two unary functions. It doesn't work as map takes two arguments:

    map :: (a -> b) -> [a] -> [b]
    

    One of possible solutions would be to explicitly bind map's first argument:

    myFunc :: Num c => (a -> c) -> [a] -> c
    myFucc f = sum . map f
    

    Alternatively you could use curry and uncurry and achieve the same result.

    myFunc = curry $ sum . uncurry map