I've started to wrap my head around it, and rather like using it for simple situations in which I can essentially pipe the values from one output to one input. A simple example of a pointfree composition I'm comfortable with would be:
let joinLines = foldr (++) "" . intersperse "\n"
While playing with GHCI today, I wanted to see if I could compose not
and (==)
to replicate (/=)
, but I wasn't really able to reason it out. (==)
take two inputs, and not
takes one. I thought that this might work:
let ne = not . (==)
With the assumption that the single Bool
output of (==)
would go to not
, but it won't compile, citing the following error:
<interactive>:1:16:
Couldn't match expected type `Bool' with actual type `a0 -> Bool'
Expected type: a0 -> Bool
Actual type: a0 -> a0 -> Bool
In the second argument of `(.)', namely `(==)'
In the expression: not . (==)
I wish I could say it meant much to me, but all I'm getting is that maybe the second argument that's passed to (==)
is mucking things up for not
? Can anybody help me understand a little better the logic behind this composition?
If you start to remove one argument at the time, you get
ne x y = not (x == y)
= (not . (x ==)) y
ne x = not . (x ==)
= not . ((==) x)
= ((not .) . (==)) x
ne = (not .) . (==)
basically, for every argument you need one (.)
, properly associated.
The type of (==)
is Eq a => a -> a -> Bool
. So if you write whatever . (==)
, and pass a value x
to that, you get whatever ((==) x)
, but (==) x
is a function a -> Bool
(where a
is the type of x
, and an instance of Eq
). So the whatever
must accept arguments of function type.
Another useful operator is (.:), which is a combinator for an initial function taking two arguments:
f . g $ x
f .: g $ x y
Explicit use of curry
and uncurry
can help switch between "multi-argument" and single-argument functions.
ne = curry (not . uncurry (==))
uncurry
"fixes" (==)
so that it takes a single argument (x,y)
rather than separate x
and y
arguments. The resulting function can then be composed with not
as expected. The composed function, then can be re-curried to accept separate arguments again.
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