Search code examples
listhaskellfunction-composition

Why does feeding init to last not work in Haskell?


So I'm writing a line to get the second to last element of a list. Initially my code was

mySLast x = last.take ((length x) - 1) x

Which worked up until the last function. Realized the my take business is already included in Haskell as init so I rewrote as

mySLast = last.init 

This still doesn't work. I find this puzzling because init::[a]->[a] and last::[a]->a so they definitely should be composable morphisms in the Hask Category.

I tried asking Haskell what it thinks the type is and it said

ghci> :t last.init
last.init :: [c] -> c
ghci> last.init [3,2,4,1]

<interactive>:45:6:
    Couldn't match expected type ‘a -> [c]’
                with actual type ‘[Integer]’
     Relevant bindings include
       it :: a -> c (bound at <interactive>:45:1)
    Possible cause: ‘init’ is applied to too many arguments
     In the second argument of ‘(.)’, namely ‘init [3, 2, 4, 1]’
     In the expression: last . init [3, 2, 4, 1]

Even though

ghci> init [3,2,4,1]
[3,2,4]
ghci> last [3,2,4]
4

So I must be misunderstanding something about composing functions in Haskell. Any insight would be greatly appreciated!


Solution

  • Function application binds more tightly than (.) so

    last.init [3,2,4,1]
    

    is being parsed as

    last . (init [3,2,4,1])
    

    you can use

    (last . init) [3,2,4,1]
    

    or

    last . init $ [3,2,4,1]