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!
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]