Consider following function definition in ghci.
let myF = sin . cos . sum
where, . stands for composition of two function (right associative). This I can call
myF [3.14, 3.14]
and it gives me desired result. Apparently, it passes list [3.14, 3.14] to function 'sum' and its 'result' is passed to cos and so on and on. However, if I do this in interpreter
let myF y = sin . cos . sum y
or
let myF y = sin . cos (sum y)
then I run into troubles. Modifying this into following gives me desired result.
let myF y = sin . cos $ sum y
or
let myF y = sin . cos . sum $ y
The type of (.) suggests that there should not be a problem with following form since 'sum y' is also a function (isn't it? After-all everything is a function in Haskell?)
let myF y = sin . cos . sum y -- this should work?
What is more interesting that I can make it work with two (or many) arguments (think of passing list [3.14, 3.14] as two arguments x and y), I have to write the following
let (myF x) y = (sin . cos . (+ x)) y
myF 3.14 3.14 -- it works!
let myF = sin . cos . (+)
myF 3.14 3.14 -- -- Doesn't work!
There is some discussion on HaskellWiki regarding this form which they call 'PointFree' form http://www.haskell.org/haskellwiki/Pointfree . By reading this article, I am suspecting that this form is different from composition of two lambda expressions. I am getting confused when I try to draw a line separating both of these styles.
Let's look at the types . For sin
and cos
we have:
cos, sin :: Floating a => a -> a
For sum
:
sum :: Num a => [a] -> a
Now, sum y
turns that into a
sum y :: Num a => a
which is a value, not a function (you could name it a function with no arguments but this is very tricky and you also need to name () -> a
functions - there was a discussion somewhere about this but I cannot find the link now - Conal spoke about it).
Anyway, trying cos . sum y
cos . sum y
won't work because .
expects both sides to have types a -> b
and b -> c
(signature is (b -> c) -> (a -> b) -> (a -> c)
) and sum y
cannot be written in this style. That's why you need to include parentheses or $
.
As for point-free style, the simples translation recipe is this:
mysum xy = x + y
we have y
at the end but we cannot remove it right now. Instead, rewriting as mysum xy = (x +) y
it works. mysum x = (x +)
mysum = (+)
(I chose a simple example, for more convoluted cases you'll have to use flip
and others)
No, sum y
is not a function. It's a number, just like sum [1, 2, 3]
is. It therefore makes complete sense that you cannot use the function composition operator (.)
with it.
Not everything in Haskell are functions.
The obligatory cryptic answer is this: (space) binds more tightly than
.
Most whitespace in Haskell can be thought of as a very high-fixity $
(the "apply" function). wx . yz
wx . yz
is basically the same as (w $ x) . (y $ z)
(w $ x) . (y $ z)
When you are first learning about $
and .
you should also make sure you learn about (space) as well, and make sure you understand how the language semantics implicitly parenthesize things in ways that may not (at first blush) appear intuitive.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.