I wrote a function:
inita xs = reverse . (drop 1) (reverse xs)
I thought it equals:
inita xs = reverse ( (drop 1) (reverse xs) )
But I had errors:
Couldn't match expected type ‘a -> [a1]’ with actual type ‘[a2]’
Relevant bindings include
xs :: [a2] (bound at ch2.hs:1:7)
init1 :: [a2] -> a -> [a1] (bound at ch2.hs:1:1)
Possible cause: ‘drop’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘(drop 1) (reverse xs)’
In the expression: reverse . (drop 1) (reverse xs)
Failed, modules loaded: none.
So what's wrong with that composition expression?
reverse ( (drop 1) (reverse xs) )
is equal to (reverse . drop 1) (reverse xs)
. But that's not what reverse . (drop 1) (reverse xs)
is parsed as, because infix operators have lower precedence than function application. For this reason, what it's actually parsed as is instead reverse . ((drop 1) (reverse xs))
, but that doesn't make any sense (i.e. doesn't typecheck), because (drop 1) (reverse xs)
is not a function but a list.
The preferred way to write such a function is
inita xs = reverse . drop 1 $ reverse xs
Here, I've replaced the high-precedence plain function application with the low-precedence $
operator (which does nothing else but apply a function, but due to the low precedence it's actually this right composition-function).
Actually though, you don't need that, because you only pass in xs
once at the end. So you might as well make reverse
part of the composition chain too:
inita xs = reverse . drop 1 . reverse $ xs
...which can simply be η-reduced to
inita = reverse . drop 1 . reverse