isMultipleOfThree num = (==0) (rem num 3)
The (== 0)
is called an operator section. It's equivalent to \x -> x == 0
, hence this is the same as
isMultipleOfThree num = (\x -> x == 0) (rem num 3)
And we immediately apply the lambda, so we get
isMultipleOfThree num = rem num 3 == 0
Now, on the other hand, your second example is
isMultipleOfThree num = (\x -> x == 0) . (rem num 3)
Now we're not applying the lambda immediately. We're applying the (.)
function, which is defined something like
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \y -> f (g y)
Hence, we have
isMultipleOfThree num = (\y -> (\x -> x == 0) ((rem num 3) y))
Now the lambda on x
is getting applied to an argument, so we can simplify the inner one
isMultipleOfThree num = (\y -> (rem num 3) y == 0)
And the parentheses around rem
are extraneous, hence
isMultipleOfThree num = (\y -> rem num 3 y == 0)
So we're applying rem
, a function of two arguments, to three arguments. Hence your error.
If you want to use (.)
to define your function, we can. But the right-hand side needs to have an argument left out.
isMultipleOfThree = (== 0) . (\x -> rem x 3)
or
isMultipleOfThree = (== 0) . (`rem` 3)
Note that we don't mention your function argument num
anymore. The composition on the right-hand side is expecting an argument. It's going to do (rem
3)on that argument and then compare the result against zero.
(.)works on functions, and both sides of the
(.)` operator should have an argument missing.
Note that what you might have been thinking of is ($)
, which is defined roughly as
($) :: (a -> b) -> (a -> b)
f $ x = f x
This really is just function application. It's not composition. We could easily write your original function as
isMultipleOfThree num = (== 0) $ (rem num 3)
The ($)
actually does behave like juxtaposition. The only point of it is to change operator precedence. We can omit parentheses in this case
isMultipleOfThree num = (== 0) $ rem num 3
and this will still work, whereas if we omit parentheses in your original function
isMultipleOfThree num = (==0) rem num 3 -- Wrong!
Now we're trying to apply the (==0)
function to three arguments, which is definitely not correct.