First of all, I am very new to Haskell and for the moment I am just trying to prepare for an exam.
I have this expression:reverse . take 3 [1 .. 10]
and what I get is an error. Is that because space operator has bigger precedence (10) than .
operator (9) and the expression above is equivalent to reverse . (take 3 [1..10])
which is reverse . ([1, 2, 3])
which is a composition between reverse and a list which makes no sense, right? I am trying to make sure I got that right, I didn't really find something similar on the internet.
In Haskell the precedence of an ordinary function call (white space, usually) is of 10. While the composition operator has a precedence of 9. It results in the case where we want to compose functions then apply it to some parameter, we have to parenthesize the composition so as to keep the application in right order.
We use the dot operator (.) to implement function composition in Haskell. Take a look at the following example code. Here, we have used function composition to calculate whether an input number is even or odd. Here, in the main function, we are calling two functions, noto and eveno, simultaneously.
Haskell - Function Composition. In mathematics, composition is denoted by f {g (x)} where g () is a function and its output in used as an input of another function, that is, f (). Function composition can be implemented using any two functions, provided the output type of one function matches with the input type of the second function.
Composing functions is a common and useful way to create new functions in Haskell. Haskell composition is based on the idea of function composition in mathematics. In mathematics, if you have two functions f ( x) and g ( x), you compute their composition as f ( g ( x)). The expression f ( g ( x)) first calls g and then calls f.
You're basically correct. Prefix function application (what you called the "space operator") binds more tightly than any infix operator does. And for completeness, the way to fix the error is to do (reverse . take 3) [1 .. 10]
or reverse . take 3 $ [1 .. 10]
instead.
I like to use GHCi and look at the types - let's see:
reverse . take 3 [1 .. 10]
error:
• Couldn't match expected typea -> [a1]
with actual type[a0]
• Possible cause:take
is applied to too many arguments
In the second argument of(.)
, namelytake 3 [1 .. 10]
In the expression:reverse . take 3 [1 .. 10]
:t take 3 [1 .. 10]
take 3 [1 .. 10] :: (Num a, Enum a) => [a]
yields type [a]
- let's see what (.)
is expecting
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
:t reverse
reverse :: [a] -> [a]
reverse fits the first part of what (.)
expects
:t take 3
take 3 :: [a] -> [a]
type fits as the second argument to what (.)
expects
:t reverse . take 3
reverse . take 3 :: [a] -> [a]
resulting function takes a list of a
and returns a list of a
, and so we only need to give it a list of a
; being explicit here:
(reverse . take 3) [1 .. 10]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With