In order to refresh my 20 year old experience with Haskell I am walking through https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/Adding_Variables_and_Assignment and at one point the following line is introduced to apply op to all the params. This is to implement e.g. (+ 1 2 3 4)
numericBinop op params = mapM unpackNum params >>= return . Number . foldl1 op
I do not understand the syntax, and the explanation in the text is a bit vague.
I understand what foldl1 does and how to dot functions (unpackNum is a helper function), but using Monads and the >>= operator leaves me a bit confused.
How is this to be read?
Essentially,
mapM unpackNum params >>= return . Number . foldl1 op
is made of two parts.
mapM unpackNum params means: take the list of parameters params. On each item, apply unpackNum: this will produce an Integer wrapped inside the ThrowsError monad. So, it's not exactly a plain Integer, since it has a chance to error out. Anyway, using unpackNum on each item either successfully produces all Integers, or throws some error. In the first case, we produce a new list of type [Integer], in the second one we (unsurprisingly) throw the error. So, the resulting type for this part is ThrowsError [Integer].
The second part is ... >>= return . Number . foldl1 op. Here >>= means: if the first part threw some error, the whole expression throws that error as well. If the part succeeded in producing [Integer] then proceed with foldl1 op, wrap the result as a Number, and finally use return to inject this value as a successful computation.
Overall there are monadic computations, but you should not think about those too much. The monadic stuff here is only propagating the errors around, or store plain values if the computation is successful. With a bit of experience, one can concentrate on the successful values only, and let mapM,>>=,return handle the error cases.
By the way, note that while the book uses code like action >>= return . f, this is arguably a bad style. One can use, to the same effect, fmap f action or f <$> action, which is a more direct way to express the same computation. E.g.
Number . foldl1 op <$> mapM unpackNum params
which is very close to a non-monadic code which ignores the error cases
-- this would work if there was no monad around, and errors did not have to be handled
Number . foldl1 op $ map unpackNum params
Your question is about syntax, so I'll just talk about how to parse that expression. Haskell's syntax is pretty simple. Informally:
identifiers separated by spaces are function application (the first identifier applied to the rest)
except identifiers that use non-alphanumeric chatracters (e.g. >>=, or .) are infix (i.e. their first argument is to the left of the identifier)
the first type of function application above (non-infix) binds more tightly than the second
operators can associate either to the left or right, and have different precedence (defined with an infix... declaration)
So only knowing this, if I see:
mapM unpackNum params >>= return . Number . foldl1 op
To begin with I know that it must be parse like
(mapM unpackNum params) >>= return . Number . (foldl1 op)
To go further we need to inspect the fixity/precedence of the two operators we see in this expression:
Prelude> :info (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in ‘GHC.Base’
infixr 9 .
Prelude> :info (>>=)
class Applicative m => Monad (m :: * -> *) where
(>>=) :: m a -> (a -> m b) -> m b
...
-- Defined in ‘GHC.Base’
infixl 1 >>=
(.) has a higher precedence (9 vs 1 for >>=), so its arguments will bind more tightly (i.e. we parenthesize them first). But how do we know which of these is correct?
(mapM unpackNum params) >>= ((return . Number) . (foldl1 op))
(mapM unpackNum params) >>= (return . (Number . (foldl1 op)))
...? Because (.) was declared infixr it associates to the right, meaning the second parse above is correct.
As Will Ness points out in the comments, (.) is associative (like e.g. addition) so both of these happen to be semantically equivalent.
With a little experience with a library (or the Prelude in this case) you learn to parse expressions with operators correctly without thinking too much.
If after doing this exercise you want to understand what a function does or how it works, then you can click through to the source of the functions you're interested in and replace occurrences of left-hand sides with right-hand sides (i.e. inline the bodies of the functions and terms). Obviously you can do this in your head or in an editor.
You could "sugar this up" with a more beginner-friendly syntax, with the do notation. Your function, numericBinop op params = mapM unpackNum params >>= return . Number . foldl1 op would become:
numericBinop op params = do
x <- mapM unpackNum params -- "<-" translates to ">>=", the bind operator
return . Number $ foldl1 op x
Well now the most mysterious is the mapM function, that is sequence . fmap, and it simply takes a function, fmaps it over the container, and flips the type, in this case (I presume) from [Number Integer] to ThrowsError [Integer], while preserving any errors (side effects) that may arise during the flipping, or in other words, if the 'flipping' caused any error, it would be represented in the result.
Not the simplest example, and you probably would be better off seeing how mapM (fmap (+1)) [Just 2, Just 3] differs from mapM (fmap (+1)) [Just 2, Nothing]. For more insights look into Traversable typeclass.
After that, you bind the [Integer] out of the ThrowsError monad and feed it to the function that takes care of doing the computation on the list, resulting in a single Integer, which in turn you need to re-embed into the ThrowsError monad with the return function after you wrap it into a Number.
If you still have trouble understanding monads, I suggest you take a look at the still relevant LYAH chapter that will gently introduce you to monads
>>= builds a computation that may fail at either end: its left argument can be an empty monad, in which case it does not even happen, otherwise its result can be empty as well. It has type
>>= :: m a -> (a -> m b) -> m b
See, its arguments are: value(s) immersed into monad and a function that accepts a pure value and returns an immersed result. This operator is a monadic version of what is known as flatMap in Scala, for instance; in Haskell, its particular implementation for lists is known as concatMap. If you have a list l, then l >>= f works as follows: for each element of l, f is applied to this element and returns a list; and all those resultant lists are concatenated to produce result.
Consider a code in Java:
try {
function1();
function2();
}
catch(Exception e) {
}
What happens when function2 is called? See, after the call to function1 the program is probably in a valid state, so function2() is an operator that transforms this current state into some different next one. But the call to function1() could result in an exception thrown, so the control would immediately transfer to the catch-block—this can be regarded as null state, so there's nothing to apply function2 to. In other words, we have the following possible control paths:
[S0] --- function1() --> [S1] --- function2() --> [S2]
[S0] --- function1() --> [] --> catch
(For simplicity, exceptions thrown from function2 are not considered in this diagram.)
So, either [S1] is a (non-empty) valid machine state, and function2 transforms it further to a (non-empty) valid [S2], or it is empty, and thus function2() is a no-op and never run. This can be summarized in pseudo-code as
S2 <- [S0] >>= function1 >>= function2
First, syntax. Whitespace is application, semantically:
f x = f $ x -- "call" f with an argument x
so your expression is actually
numericBinop op params = ((mapM unpackNum) params) >>= return . Number . (foldl1 op)
Next, the operators are built from non-alphanumerical characters, without any whitespace. Here, there's . and >>=. Running :i (.) and :i (>>=) at GHCi reveals their fixity specs are infixl 9 . and infixr 1 >>=. 9 is above 1 so . is stronger than >>=; thus
= ((mapM unpackNum) params) >>= (return . Number . (foldl1 op))
infixl 9 . means . associates to the right, thus, finally, it is
= ((mapM unpackNum) params) >>= (return . (Number . (foldl1 op)))
The (.) is defined as (f . g) x = f (g x), thus (f . (g . h)) x = f ((g . h) x) = f (g (h x)) = (f . g) (h x) = ((f . g) . h) x; by eta-reduction we have
(f . (g . h)) = ((f . g) . h)
thus (.) is associative, and so parenthesization is optional. We'll drop the explicit parens with the "whitespace" application from now on as well. Thus we have
numericBinop op params = (mapM unpackNum params) >>=
(\ x -> return (Number (foldl1 op x))) -- '\' is for '/\'ambda
Monadic sequences are easier written with do, and the above is equivalent to
= do
{ x <- mapM unpackNum params -- { ; } are optional, IF all 'do'
; return (Number (foldl1 op x))) -- lines are indented at the same level
}
Next, mapM can be defined as
mapM f [] = return []
mapM f (x:xs) = do { x <- f x ;
xs <- mapM f xs ;
return (x : xs) }
and the Monad Laws demand that
do { r <- do { x ; === do { x ;
y } ; r <- y ;
foo r foo r
} }
(you can find an overview of do notation e.g. in this recent answer of mine); thus,
numericBinop op [a, b, ..., z] =
do {
a <- unpackNum a ;
b <- unpackNum b ;
...........
z <- unpackNum z ;
return (Number (foldl1 op [a, b, ..., z]))
}
(you may have noticed my use of x <- x bindings -- we can use the same variable name on both sides of <-, because monadic bindings are not recursive -- thus introducing shadowing.)
This is now clearer, hopefully.
But, I said "first, syntax". So now, the meaning of it. By same Monad Laws,
numericBinop op [a, b, ..., y, z] =
do {
xs <- do { a <- unpackNum a ;
b <- unpackNum b ;
...........
y <- unpackNum y ;
return [a, b, ..., y] } ;
z <- unpackNum z ;
return (Number (op (foldl1 op xs) z))
}
thus, we need only understand the sequencing of two "computations", c and d,
do { a <- c ; b <- d ; return (foo a b) }
=
c >>= (\ a ->
d >>= (\ b ->
return (foo a b) ))
for a particular monad involved, which is determined by the bind (>>=) operator's implementation for a given monad.
Monads are EDSLs for generalized function composition. The sequencing of computations involves not only the explicit expressions appearing in the do sequence, but also the implicit effects peculiar to the particular monad in question, performed in principled and consistent manner behind the scenes. Which is the whole point to having monads in the first place (well, one of the main points, at least).
Here the monad involved appears to concern itself with the possibility of failure, and early bail-outs in the event that failure indeed happens.
So, with the do code we write the essence of what we intend to happen, and the possibility of intermittent failure is automatically taken care of, for us, behind the scenes.
In other words, if one of unpackNum computations fails, so will the whole of the combined computation fail, without attempting any of the subsequent unpackNum sub-computations. But if all of them succeed, so will the combined computation.
Related
What is the difference between the dot (.) and the dollar sign ($)?
As I understand it, they are both syntactic sugar for not needing to use parentheses.
The $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.
For example, let's say you've got a line that reads:
putStrLn (show (1 + 1))
If you want to get rid of those parentheses, any of the following lines would also do the same thing:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
The primary purpose of the . operator is not to avoid parentheses, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parentheses, but works differently.
Going back to the same example:
putStrLn (show (1 + 1))
(1 + 1) doesn't have an input, and therefore cannot be used with the . operator.
show can take an Int and return a String.
putStrLn can take a String and return an IO ().
You can chain show to putStrLn like this:
(putStrLn . show) (1 + 1)
If that's too many parentheses for your liking, get rid of them with the $ operator:
putStrLn . show $ 1 + 1
They have different types and different definitions:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($) is intended to replace normal function application but at a different precedence to help avoid parentheses. (.) is for composing two functions together to make a new function.
In some cases they are interchangeable, but this is not true in general. The typical example where they are is:
f $ g $ h $ x
==>
f . g . h $ x
In other words in a chain of $s, all but the final one can be replaced by .
Also note that ($) is the identity function specialised to function types. The identity function looks like this:
id :: a -> a
id x = x
While ($) looks like this:
($) :: (a -> b) -> (a -> b)
($) = id
Note that I've intentionally added extra parentheses in the type signature.
Uses of ($) can usually be eliminated by adding parenthesis (unless the operator is used in a section). E.g.: f $ g x becomes f (g x).
Uses of (.) are often slightly harder to replace; they usually need a lambda or the introduction of an explicit function parameter. For example:
f = g . h
becomes
f x = (g . h) x
becomes
f x = g (h x)
($) allows functions to be chained together without adding parentheses to control evaluation order:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
The compose operator (.) creates a new function without specifying the arguments:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
The example above is arguably illustrative, but doesn't really show the convenience of using composition. Here's another analogy:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
If we only use third once, we can avoid naming it by using a lambda:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
Finally, composition lets us avoid the lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
The short and sweet version:
($) calls the function which is its left-hand argument on the value which is its right-hand argument.
(.) composes the function which is its left-hand argument on the function which is its right-hand argument.
One application that is useful and took me some time to figure out from the very short description at Learn You a Haskell: Since
f $ x = f x
and parenthesizing the right hand side of an expression containing an infix operator converts it to a prefix function, one can write ($ 3) (4 +) analogous to (++ ", world") "hello".
Why would anyone do this? For lists of functions, for example. Both:
map (++ ", world") ["hello", "goodbye"]
map ($ 3) [(4 +), (3 *)]
are shorter than
map (\x -> x ++ ", world") ["hello", "goodbye"]
map (\f -> f 3) [(4 +), (3 *)]
Obviously, the latter variants would be more readable for most people.
Haskell: difference between . (dot) and $ (dollar sign)
What is the difference between the dot (.) and the dollar sign ($)?. As I understand it, they are both syntactic sugar for not needing to use parentheses.
They are not syntactic sugar for not needing to use parentheses - they are functions, - infixed, thus we may call them operators.
Compose, (.), and when to use it.
(.) is the compose function. So
result = (f . g) x
is the same as building a function that passes the result of its argument passed to g on to f.
h = \x -> f (g x)
result = h x
Use (.) when you don't have the arguments available to pass to the functions you wish to compose.
Right associative apply, ($), and when to use it
($) is a right-associative apply function with low binding precedence. So it merely calculates the things to the right of it first. Thus,
result = f $ g x
is the same as this, procedurally (which matters since Haskell is evaluated lazily, it will begin to evaluate f first):
h = f
g_x = g x
result = h g_x
or more concisely:
result = f (g x)
Use ($) when you have all the variables to evaluate before you apply the preceding function to the result.
We can see this by reading the source for each function.
Read the Source
Here's the source for (.):
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
And here's the source for ($):
-- | Application operator. This operator is redundant, since ordinary
-- application #(f x)# means the same as #(f '$' x)#. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as #'map' ('$' 0) xs#,
-- or #'Data.List.zipWith' ('$') fs xs#.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Conclusion
Use composition when you do not need to immediately evaluate the function. Maybe you want to pass the function that results from composition to another function.
Use application when you are supplying all arguments for full evaluation.
So for our example, it would be semantically preferable to do
f $ g x
when we have x (or rather, g's arguments), and do:
f . g
when we don't.
... or you could avoid the . and $ constructions by using pipelining:
third xs = xs |> tail |> tail |> head
That's after you've added in the helper function:
(|>) x y = y x
My rule is simple (I'm beginner too):
do not use . if you want to pass the parameter (call the function), and
do not use $ if there is no parameter yet (compose a function)
That is
show $ head [1, 2]
but never:
show . head [1, 2]
A great way to learn more about anything (any function) is to remember that everything is a function! That general mantra helps, but in specific cases like operators, it helps to remember this little trick:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and
:t ($)
($) :: (a -> b) -> a -> b
Just remember to use :t liberally, and wrap your operators in ()!
All the other answers are pretty good. But there’s an important usability detail about how ghc treats $, that the ghc type checker allows for instatiarion with higher rank/ quantified types. If you look at the type of $ id for example you’ll find it’s gonna take a function whose argument is itself a polymorphic function. Little things like that aren’t given the same flexibility with an equivalent upset operator. (This actually makes me wonder if $! deserves the same treatment or not )
The most important part about $ is that it has the lowest operator precedence.
If you type info you'll see this:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
This tells us it is an infix operator with right-associativity that has the lowest possible precedence. Normal function application is left-associative and has highest precedence (10). So $ is something of the opposite.
So then we use it where normal function application or using () doesn't work.
So, for example, this works:
λ> head . sort $ "example"
λ> e
but this does not:
λ> head . sort "example"
because . has lower precedence than sort and the type of (sort "example") is [Char]
λ> :type (sort "example")
(sort "example") :: [Char]
But . expects two functions and there isn't a nice short way to do this because of the order of operations of sort and .
I think a short example of where you would use . and not $ would help clarify things.
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
Note that times6 is a function that is created from function composition.
I am able to understand the basics of point-free functions in Haskell:
addOne x = 1 + x
As we see x on both sides of the equation, we simplify it:
addOne = (+ 1)
Incredibly it turns out that functions where the same argument is used twice in different parts can be written point-free!
Let me take as a basic example the average function written as:
average xs = realToFrac (sum xs) / genericLength xs
It may seem impossible to simplify xs, but http://pointfree.io/ comes out with:
average = ap ((/) . realToFrac . sum) genericLength
That works.
As far as I understand this states that average is the same as calling ap on two functions, the composition of (/) . realToFrac . sum and genericLength
Unfortunately the ap function makes no sense whatsoever to me, the docs http://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Monad.html#v:ap state:
ap :: Monad m => m (a -> b) -> m a -> m b
In many situations, the liftM operations can be replaced by uses of ap,
which promotes function application.
return f `ap` x1 `ap` ... `ap` xn
is equivalent to
liftMn f x1 x2 ... xn
But writing:
let average = liftM2 ((/) . realToFrac . sum) genericLength
does not work, (gives a very long type error message, ask and I'll include it), so I do not understand what the docs are trying to say.
How does the expression ap ((/) . realToFrac . sum) genericLength work? Could you explain ap in simpler terms than the docs?
Any lambda term can be rewritten to an equivalent term that uses just a set of suitable combinators and no lambda abstractions. This process is called abstraciton elimination. During the process you want to remove lambda abstractions from inside out. So at one step you have λx.M where M is already free of lambda abstractions, and you want to get rid of x.
If M is x, you replace λx.x with id (id is usually denoted by I in combinatory logic).
If M doesn't contain x, you replace the term with const M (const is usually denoted by K in combinatory logic).
If M is PQ, that is the term is λx.PQ, you want to "push" x inside both parts of the function application so that you can recursively process both parts. This is accomplished by using the S combinator defined as λfgx.(fx)(gx), that is, it takes two functions and passes x to both of them, and applies the results together. You can easily verify that that λx.PQ is equivalent to S(λx.P)(λx.Q), and we can recursively process both subterms.
As described in the other answers, the S combinator is available in Haskell as ap (or <*>) specialized to the reader monad.
The appearance of the reader monad isn't accidental: When solving the task of replacing λx.M with an equivalent function is basically lifting M :: a to the reader monad r -> a (actually the reader Applicative part is enough), where r is the type of x. If we revise the process above:
The only case that is actually connected with the reader monad is when M is x. Then we "lift" x to id, to get rid of the variable. The other cases below are just mechanical applications of lifting an expression to an applicative functor:
The other case λx.M where M doesn't contain x, it's just lifting M to the reader applicative, which is pure M. Indeed, for (->) r, pure is equivalent to const.
In the last case, <*> :: f (a -> b) -> f a -> f b is function application lifted to a monad/applicative. And this is exactly what we do: We lift both parts P and Q to the reader applicative and then use <*> to bind them together.
The process can be further improved by adding more combinators, which allows the resulting term to be shorter. Most often, combinators B and C are used, which in Haskell correspond to functions (.) and flip. And again, (.) is just fmap/<$> for the reader applicative. (I'm not aware of such a built-in function for expressing flip, but it'd be viewed as a specialization of f (a -> b) -> a -> f b for the reader applicative.)
Some time ago I wrote a short article about this: The Monad Reader Issue 17, The Reader Monad and Abstraction Elimination.
When the monad m is (->) a, as in your case, you can define ap as follows:
ap f g = \x -> f x (g x)
We can see that this indeed "works" in your pointfree example.
average = ap ((/) . realToFrac . sum) genericLength
average = \x -> ((/) . realToFrac . sum) x (genericLength x)
average = \x -> (/) (realToFrac (sum x)) (genericLength x)
average = \x -> realToFrac (sum x) / genericLength x
We can also derive ap from the general law
ap f g = do ff <- f ; gg <- g ; return (ff gg)
that is, desugaring the do-notation
ap f g = f >>= \ff -> g >>= \gg -> return (ff gg)
If we substitute the definitions of the monad methods
m >>= f = \x -> f (m x) x
return x = \_ -> x
we get the previous definition of ap back (for our specific monad (->) a). Indeed:
app f g
= f >>= \ff -> g >>= \gg -> return (ff gg)
= f >>= \ff -> g >>= \gg -> \_ -> ff gg
= f >>= \ff -> g >>= \gg _ -> ff gg
= f >>= \ff -> \x -> (\gg _ -> ff gg) (g x) x
= f >>= \ff -> \x -> (\_ -> ff (g x)) x
= f >>= \ff -> \x -> ff (g x)
= f >>= \ff x -> ff (g x)
= \y -> (\ff x -> ff (g x)) (f y) y
= \y -> (\x -> f y (g x)) y
= \y -> f y (g y)
The Simple Bit: fixing liftM2
The problem in the original example is that ap works a bit differently from the liftM functions. ap takes a function wrapped up in a monad, and applies it to an argument wrapped up in a monad. But the liftMn functions take a "normal" function (one which is not wrapped up in a monad) and apply it to argument(s) that are wrapped up in monads.
I'll explain more about what that means below, but the upshot is that if you want to use liftM2, then you have to pull (/) out and make it a separate argument at the beginning. (So in this case (/) is the "normal" function.)
let average = liftM2 ((/) . realToFrac . sum) genericLength -- does not work
let average = liftM2 (/) (realToFrac . sum) genericLength -- works
As posted in the original question, calling liftM2 should involve three agruments: liftM2 f x1 x2. Here the f is (/), x1 is (realToFrac . sum) and x2 is genericLength.
The version posted in the question (the one which doesn't work) was trying to call liftM2 with only two arguments.
The explanation
I'll build this up in a few stages. I'll start with some specific values, and build up to a function that can take any set of values. Jump to the last section for the TL:DR
In this example, lets assume the list of numbers is [1,2,3,4]. The sum of these numbers is 10, and the length of the list is 4. The average is 10/4 or 2.5.
To shoe-horn this into the right form for ap, we're going to break this into a function, an input, and a result.
ourFunction = (10/) -- "divide 10 by"
ourInput = 4
ourResult = 2.5
Three kinds of Function Application
ap and listM both involve monads. At this point in the explanation, you can think of a monad as something that a value can be "wrapped up in". I'll give a better definition below.
Normal function application applies a normal function to a normal input. liftM applies a normal function to an input wrapped in a monad, and ap applies a function wrapped in a monad to an input wrapped in a monad.
(10/) 4 -- returns 2.5
liftM (10/) monad(4) -- returns monad(2.5)
ap monad(10/) monad(4) -- returns monad(2.5)
(Note that this is pseudocode. monad(4) is not actually valid Haskell).
(Note that liftM is a different function from liftM2, which was used earlier. liftM takes a function and only one argument, which is a better fit for the pattern i'm describing.)
In the average function defined above, the monads were functions, but "functions-as-monads" can be hard to talk about, so I'll start with simpler examples.
So what's a monad?
A better description of a monad is "something which contains a value, or produces a value, or which you can somehow extract a value from, but which also has something more complicated going on."
That's a really vague description, but it kind of has to be, because the "something more complicated" can be a lot of different things.
Monads can be confusing, but the point of them is that when you use monad operations (like ap and liftM) they will take care of the "something more complicated" for you, so you can just concentrate on the values.
That's probably still not very clear, so let's do some examples:
The Maybe monad
ap (Just (10/)) (Just 4) -- result is (Just 2.5)
One of the simplest monads is 'Maybe'. The value is whatever is contained inside a Just. So if we call ap and give it (Just ourFunction) and (Just ourInput) then we get back (Just ourResult).
The "something more complicated" is the fact that there might not be a value there at all, and you have to allow for the Nothing case.
As mentioned, the point of using a function like ap is that it takes care of these extra complications for us. With the Maybe monad, ap handles this by returning Nothing if either the Maybe-function or the Maybe-input were Nothing.
ap (Just (10/)) Nothing -- result is Nothing
ap Nothing (Just 4) -- result is Nothing
The List Monad
ap [(10/)] [4] -- result is [2.5]
With the list Monad, the value is whatever is inside the list. So ap [ourfunction] [ourInput] returns [ourResult].
The "something more complicated" is that there may be more than one thing inside the list (or exactly one thing, or nothing at all).
With lists, that means ap takes a list of zero or more functions, and a list of zero or more inputs. It handles that by returning a list of zero or more results: one result for every possible combination of function and input.
ap [(10/), (100/)] [5,4,2] -- result is [2.0, 2.5, 5.0, 20.0, 25.0, 50.0]
Functions as Monads
A function like genericLength is considered a Monad because it has a value (the function's output), and it has a "something more complicated" (the fact that you have to supply an input before you can get the value).
This is where it gets a little confusing, because we're dealing with multiple functions, multiple inputs, and multiple results. It is all well defined, it's just hard to describe, so we have to be careful with our terminology.
Lets start with the list [1,2,3,4], and call that our "original input". That's the list we're trying to find the average of. It's the xs argument in the original average function.
If we give our original input ([1,2,3,4]) to genericLength then we get a value of '4'.
Our other function is ((/) . realToFrac . sum). It takes our list [1,2,3,4] and finds the sum (10), turns that into a fractional value, and then feeds it as the first argument to (/). The result is an incomplete division function that is waiting for another argument. ie it takes [1,2,3,4] as an input, and produces (10/) as its output.
This all fits with the way ap is defined for functions. With functions, ap takes two things. The first is a function that reads the original input and produces a new function. The second is a function that reads the original input and produces a new input. The final result is a function that takes the original input, and returns the same thing you would get if you applied the new function to the new input.
You might have to read that a few times to make sense of it. Alternatively, here it is in pseudocode:
average =
ap
(functionThatTakes [1,2,3,4] and returns "(10/)" )
(functionThatTakes [1,2,3,4] and returns " 4 " )
-- which means:
average =
(functionThatTakes [1,2,3,4] and returns "2.5" )
If you compare this to the simpler examples above, you'll see that it still has our function (10/), our input 4 and our result 2.5. And each of them is once again wrapped up in the "something more complicated". In this case, the "something more complicated" is the "function that takes [1,2,3,4] and returns...".
Of course, since they're functions, they don't have to take [1,2,3,4] as their input. If they took a different list of integers (eg [1,2,3,4,5]) then we would get different results (e.g. new function: (15/), new input 5 and new value 3).
Other examples
minPlusMax = ap ((+) . minimum) maximum
-- a function that adds the minimum element of a list, to the maximum element
upperAndLower = ap ((,) . toUpper) toLower
-- a function that takes a Char and returns a tuple, with the upper case and lower case versions of a character
These could all also be defined using liftM2.
average = liftM2 (/) sum genericLength
minPlusMax = liftM2 (+) minimum maximum
upperAndLower = liftM2 (,) toUpper toLower
I'm trying to understand order of execution in purely functional language.
I know that in purely functional languages, there is no necessary execution order.
So my question is:
Suppose there are two functions.
I would like to know all ways in which I can call one function after another (except nested call of one function from another) (and except io-mode).
I would like to see examples in Haskell or pseudo-code.
There is no way to do what you describe, if the functions are totally independent and you don't use the result of one when you call the other.
This is because there is no reason to do this. In a side effect free setting, calling a function and then ignoring its result is exactly the same as doing nothing for the amount of time it takes to call that function (setting aside memory usage).
It is possible that seq x y will evaluate x and then y, and then give you y as its result, but this evaluation order isn't guaranteed.
Now, if we do have side effects, such as if we are working inside a Monad or Applicative, this could be useful, but we aren't truly ignoring the result since there is context being passed implicitly. For instance, you can do
main :: IO ()
main = putStrLn "Hello, " >> putStrLn "world"
in the IO Monad. Another example would be the list Monad (which could be thought of as representing a nondeterministic computation):
biggerThanTen :: Int -> Bool
biggerThanTen n = n > 10
example :: String
example = filter biggerThanTen [1..15] >> return 'a' -- This evaluates to "aaaaa"
Note that even here we aren't really ignoring the result. We ignore the specific values, but we use the structure of the result (in the second example, the structure would be the fact that the resulting list from filter biggerThanTen [1..15] has 5 elements).
I should point out, though, that things that are sequenced in this way aren't necessarily evaluated in the order that they are written. You can sort of see this with the list Monad example. This becomes more apparent with bigger examples though:
example2 :: [Int]
example2 =
[1,2,3] >>=
(\x -> [10,100,1000] >>=
(\y -> return (x * y))) -- ==> [10,100,1000,20,200,2000,30,300,3000]
The main takeaway here is that evaluation order (in the absence of side effects like IO and ignoring bottoms) doesn't affect the ultimate meaning of code in Haskell (other than possible differences in efficiency, but that is another topic). As a result, there is never a reason to call two functions "one after another" in the fashion described in the question (that is, where the calls are totally independent from each other).
Do notation
Do notation is actually exactly equivalent to using >>= and >> (there is actually one other thing involved that takes care of pattern match failures, but that is irrelevant to the discussion at hand). The compiler actually takes things written in do notation and converts them to >>= and >> through a process called "desugaring" (since it removes the syntactic sugar). Here are the three examples from above written with do notation:
IO Example
main :: IO ()
main = do
putStrLn "Hello, "
putStrLn "World"
First list example
biggerThanTen :: Int -> Bool
biggerThanTen n = n > 10
example :: String -- String is a synonym for [Char], by the way
example = do
filter biggerThanTen [1..15]
return 'a'
Second list example
example2 :: [Int]
example2 = do
x <- [1,2,3]
y <- [10,100,1000]
return (x * y)
Here is a side-by-side comparison of the conversions:
do --
m -- m >> n
n --
do --
x <- m -- m >>= (\x ->
... -- ...)
The best way to understand do notation is to first understand >>= and return since, as I said, that's what the compiler transforms do notation into.
As a side-note, >> is just the same as >>=, it just ignores the "result" of it's left argument (although it preserves the "context" or "structure"). So all definitions of >> must be equivalent to m >> n = m >>= (\_ -> n).
Expanding the >>= in the second list example
To help drive home the point that Monads are not usually impure, lets expand the >>= calls in the second list example, using the Monad definition for lists. The definition is:
instance Monad [] where
return x = [x]
xs >>= f = concatMap f xs
and we can convert example2 into:
Step 0 (what we already have)
example2 :: [Int]
example2 =
[1,2,3] >>=
(\x -> [10,100,1000] >>=
(\y -> return (x * y)))
Step 1 (converting the first >>=)
example2 =
concatMap
(\x -> [10,100,1000] >>=
(\y -> return (x * y)))
[1,2,3]
Step 2
example2 =
concatMap
(\x -> concatMap
(\y -> return (x * y))
[10,100,1000])
[1,2,3]
Step 3
example2 =
concatMap
(\x -> concatMap
(\y -> [x * y])
[10,100,1000])
[1,2,3]
So, there is no magic going on here, just normal function calls.
You can write a function whose arguments depend on the evaluation of another function:
-- Ads the first two elements of a list together
myFunc :: [Int] -> Int
myFunc xs = (head xs) + (head $ tail xs)
If that's what you mean. In this case, you can't get the output of myFunc xs without evaluating head xs, head $ tail xs and (+). There is an order here. However, the compiler can choose which order to execute head xs and head $ tail xs in since they are not dependent on each other, but it can't do the addition without having both of the other results. It could even choose to evaluate them in parallel, or on different machines. The point is that pure functions, because they have no side effects, don't have to be evaluated in a given order until their results are interdependent.
Another way to look at the above function is as a graph:
myFunc
|
(+)
/ \
/ \
head head
\ |
\ tail
\ /
xs
In order to evaluate a node, all nodes below it have to be evaluated first, but different branches can be evaluated in parallel. First xs must be evaluated, at least partially, but after that the two branches can be evaluated in parallel. There are some nuances due to lazy evaluation, but this is essentially how the compiler constructs evaluation trees.
If you really want to force one function call before the other, you can use the seq function. It takes two arguments, forces the first to be evaluated, then returns the second, e.g.
myFunc2 :: [Int] -> Int
myFunc2 xs = hxs + (hxs `seq` (head $ tail xs))
where hxs = head xs
This will force head xs to evaluate before head $ tail xs, but this is more dealing with strictness than sequencing functions.
Here is an easy way:
case f x of
result1 -> case g y of
result2 -> ....
Still, unless g y uses something from result1 and the subsequent calculations something from result2, or the pattern is such that the result must be evaluated, there is no guarantee that either of f or g are actually called, nor in what order.
Still, you wanted a way to call one function after another, and this is such a way.
I am trying to understand Haskell monads, reading "Monads for the Curious Programmer". I've run into the example of List Monad:
tossDie=[1,2,3,4,5,6]
toss2Dice = do
n <- tossDie
m <- tossDie
return (n+m)
main = print toss2Dice
The way do block produces m as 36-element list I sort of understand - it maps every element of n as a list of 6 elements and then concatenates those lists. What I do not understand is how n is changed by the presence of m <- tossDie, from 6 elements list to 36 elements. Obviously "we first bind n and then bind m" is wrong understanding here, but what is right?
I am also not fully clear on how two-argument function is applied in do block. I suspect it's a case of curying, but I am slightly hazy as to how exactly it works.
Can someone please explain the above two mysteries?
For lists (such as tossDie), the do notation acts like a list comprehension -- that is to say, as if each variable binding were a nested foreach loop.
The do-block expression:
toss2Dice = do { n <- tossDie; m <- tossDie; return (n+m) }
does the same thing as this list comprehension:
toss2Dice = [ n+m | n <- tossDie, m <- tossDie ]
The result is comparable to the following imperative pseudocode:
toss2Dice = []
foreach n in tossDie:
foreach m in tossDie:
toss2Dice.push_back(n+m)
except that the Haskell examples generate their results lazily, on demand, instead of eagerly and all at once.
If you look at the monad instance for lists, you can see how this works:
instance Monad [] where
xs >>= f = concat (map f xs)
return x = [x]
Starting at the beginning of the do block, each variable binding creates a loop over the remainder of the block:
do { n <- tossDie; m <- tossDie; return (n+m) }
===> tossDie >>= \n -> do { m <- tossDie; return (n+m) }
===> concat ( map (\n -> do { m <- tossDie; return (n+m) }) tossDie )
Note that map function iterates over the items in the list tossDie, and the results are concatenated. The mapping function is the remainder of the do block, so the first binding effectively creates an outer loop around it.
Additional bindings create successively nested loops; and finally, the return function creates a singleton list out of each computed value (n+m) so that the "bind" function >>= (which expects lists) can concatenate them properly.
The interesting bit I assume is this:
toss2Dice = do
n <- tossDie
m <- tossDie
return (n+m)
This is somewhat equivalent to the following Python:
def toss2dice():
for n in tossDie:
for m in tossDie:
yield (n+m)
When it comes to the list monad, you can view the binding arrows (<-) in do notation as traditional imperative "foreach" loops. Everything after
n <- tossDie
belongs to the "loop body" of that foreach loop, and so will be evaluated once for every value in tossDie assigned to n.
If you want the desugaring from do notation to actual bind operators >>=, it looks like this:
toss2Dice =
tossDie >>= (\n ->
tossDie >>= (\m ->
return (n+m)
)
)
Notice how the "inner loop body"
(\n ->
tossDie >>= (\m ->
return (n+m)
)
)
Will get executed once for every value in tossDie. This is pretty much the equivalent to the nested Python loops.
Technical mumbo-jumbo: The reason you get "foreach" loops from the binding arrows has to do with the particular monad you are working with. The arrows mean different things for different monads, and to know what they mean for a particular monad you have to do some sleuthing and figure out how that monad works in general.
The arrows get desugared into calls to the bind operator, >>=, which works differently for different monads as well – this is the reason the bind arrows <- also work differently for different monads!
In the case of the list monad, the bind operator >>= takes a list to the left and a function returning a list to the right, and sort of applies that function to every element of the list. If we want to double every element in a list in a cumbersome way, we could imagine doing it as
λ> [1, 2, 3, 4] >>= \n -> return (n*2)
[2,4,6,8]
(return is required to make the types work out. >>= expects a function that returns a list, and return will, for the list monad, wrap a value in a list.) To illustrate a perhaps more powerful example, we can start by imagining the function
λ> let posneg n = [n, -n]
λ> posneg 5
[5,-5]
Then we can write
λ> [1, 2, 3, 4] >>= posneg
[1,-1,2,-2,3,-3,4,-4]
to count the natural numbers between -4 and 4.
The reason the list monad works this way is that this particular behaviour of the bind operator >>= and return makes the monad laws hold. The monad laws are important for us (and perhaps the adventurous compiler) because they let us change code in ways that we know will not break anything.
A very cute side effect of this is that it makes lists very handy to represent uncertainty in values: Say you are building an OCR thingey that's supposed to look at an image and turn it into text. You might encounter a character that could be either 4 or A or H, but you are not sure. By letting the OCR thingey work in the list monad and return the list ['A', '4', 'H'] you have covered your bases. Actually working with the scanned text then become very easy and readable with do notation for the list monad. (It sorta looks like you're working with single values, when in fact you are just generating all possible combinations!)
Adding to #kqr answer:
>>= for list monad is actually concatMap, a function that maps elements to lists of elements and concatenates the lists, but with arguments flipped:
concatMap' x f = concat (map f x)
or alternatively
concatMap' = flip concatMap
return is just
singleElementList x = [x]
Now we can replace >>= with concatMap' and singleElementList:
toss2Dice =
concatMap' tossDie (\n ->
concatMap' tossDie (\m ->
singleElementList (n+m)
)
)
Now we can replace the 2 functions with their bodies:
toss2Dice =
concat (map (\n ->
concat (map (\m ->
[n+m]
) tossDice)
) tossDice)
Remove extra line breaks:
toss2Dice = concat (map (\n -> concat (map (\m -> [n+m]) tossDice)) tossDice)
Or shorter with concatMap:
toss2Dice = concatMap (\n -> concatMap (\m -> [n+m]) tossDice) tossDice
following nponeccop's advice, with
for = flip concatMap
your code becomes
toss2Dice =
for {- n in -} tossDie {- call -}
(\n-> for {- m in -} tossDie {- call -}
(\m-> [n+m]))
where it is plainly visible that we have nested functions, one inside another; so the inner function (\m-> [n+m]), being in the scope of outer function's argument n, has access to it (to the argument n that is). So it uses the value of the argument to the outer function, which is the same on each invocation of the inner function, however many times it is invoked during the same invocation of the outer function.
This can be re-written with named functions,
toss2Dice =
for {- each elem in -} tossDie {- call -} g
where g n = for {- each elem in -} tossDie {- call -} h
where h m = [n+m]
The function h is defined inside g, i.e. in g's argument's scope. And that's how h gets to use both m and n even though only m is its argument.
So in fact we do indeed "first bind n and then bind m" here. In nested fashion, that is.
What is the difference between the dot (.) and the dollar sign ($)?
As I understand it, they are both syntactic sugar for not needing to use parentheses.
The $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.
For example, let's say you've got a line that reads:
putStrLn (show (1 + 1))
If you want to get rid of those parentheses, any of the following lines would also do the same thing:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
The primary purpose of the . operator is not to avoid parentheses, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parentheses, but works differently.
Going back to the same example:
putStrLn (show (1 + 1))
(1 + 1) doesn't have an input, and therefore cannot be used with the . operator.
show can take an Int and return a String.
putStrLn can take a String and return an IO ().
You can chain show to putStrLn like this:
(putStrLn . show) (1 + 1)
If that's too many parentheses for your liking, get rid of them with the $ operator:
putStrLn . show $ 1 + 1
They have different types and different definitions:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($) is intended to replace normal function application but at a different precedence to help avoid parentheses. (.) is for composing two functions together to make a new function.
In some cases they are interchangeable, but this is not true in general. The typical example where they are is:
f $ g $ h $ x
==>
f . g . h $ x
In other words in a chain of $s, all but the final one can be replaced by .
Also note that ($) is the identity function specialised to function types. The identity function looks like this:
id :: a -> a
id x = x
While ($) looks like this:
($) :: (a -> b) -> (a -> b)
($) = id
Note that I've intentionally added extra parentheses in the type signature.
Uses of ($) can usually be eliminated by adding parenthesis (unless the operator is used in a section). E.g.: f $ g x becomes f (g x).
Uses of (.) are often slightly harder to replace; they usually need a lambda or the introduction of an explicit function parameter. For example:
f = g . h
becomes
f x = (g . h) x
becomes
f x = g (h x)
($) allows functions to be chained together without adding parentheses to control evaluation order:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
The compose operator (.) creates a new function without specifying the arguments:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
The example above is arguably illustrative, but doesn't really show the convenience of using composition. Here's another analogy:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
If we only use third once, we can avoid naming it by using a lambda:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
Finally, composition lets us avoid the lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
The short and sweet version:
($) calls the function which is its left-hand argument on the value which is its right-hand argument.
(.) composes the function which is its left-hand argument on the function which is its right-hand argument.
One application that is useful and took me some time to figure out from the very short description at Learn You a Haskell: Since
f $ x = f x
and parenthesizing the right hand side of an expression containing an infix operator converts it to a prefix function, one can write ($ 3) (4 +) analogous to (++ ", world") "hello".
Why would anyone do this? For lists of functions, for example. Both:
map (++ ", world") ["hello", "goodbye"]
map ($ 3) [(4 +), (3 *)]
are shorter than
map (\x -> x ++ ", world") ["hello", "goodbye"]
map (\f -> f 3) [(4 +), (3 *)]
Obviously, the latter variants would be more readable for most people.
Haskell: difference between . (dot) and $ (dollar sign)
What is the difference between the dot (.) and the dollar sign ($)?. As I understand it, they are both syntactic sugar for not needing to use parentheses.
They are not syntactic sugar for not needing to use parentheses - they are functions, - infixed, thus we may call them operators.
Compose, (.), and when to use it.
(.) is the compose function. So
result = (f . g) x
is the same as building a function that passes the result of its argument passed to g on to f.
h = \x -> f (g x)
result = h x
Use (.) when you don't have the arguments available to pass to the functions you wish to compose.
Right associative apply, ($), and when to use it
($) is a right-associative apply function with low binding precedence. So it merely calculates the things to the right of it first. Thus,
result = f $ g x
is the same as this, procedurally (which matters since Haskell is evaluated lazily, it will begin to evaluate f first):
h = f
g_x = g x
result = h g_x
or more concisely:
result = f (g x)
Use ($) when you have all the variables to evaluate before you apply the preceding function to the result.
We can see this by reading the source for each function.
Read the Source
Here's the source for (.):
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
And here's the source for ($):
-- | Application operator. This operator is redundant, since ordinary
-- application #(f x)# means the same as #(f '$' x)#. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as #'map' ('$' 0) xs#,
-- or #'Data.List.zipWith' ('$') fs xs#.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Conclusion
Use composition when you do not need to immediately evaluate the function. Maybe you want to pass the function that results from composition to another function.
Use application when you are supplying all arguments for full evaluation.
So for our example, it would be semantically preferable to do
f $ g x
when we have x (or rather, g's arguments), and do:
f . g
when we don't.
... or you could avoid the . and $ constructions by using pipelining:
third xs = xs |> tail |> tail |> head
That's after you've added in the helper function:
(|>) x y = y x
My rule is simple (I'm beginner too):
do not use . if you want to pass the parameter (call the function), and
do not use $ if there is no parameter yet (compose a function)
That is
show $ head [1, 2]
but never:
show . head [1, 2]
A great way to learn more about anything (any function) is to remember that everything is a function! That general mantra helps, but in specific cases like operators, it helps to remember this little trick:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and
:t ($)
($) :: (a -> b) -> a -> b
Just remember to use :t liberally, and wrap your operators in ()!
All the other answers are pretty good. But there’s an important usability detail about how ghc treats $, that the ghc type checker allows for instatiarion with higher rank/ quantified types. If you look at the type of $ id for example you’ll find it’s gonna take a function whose argument is itself a polymorphic function. Little things like that aren’t given the same flexibility with an equivalent upset operator. (This actually makes me wonder if $! deserves the same treatment or not )
The most important part about $ is that it has the lowest operator precedence.
If you type info you'll see this:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
This tells us it is an infix operator with right-associativity that has the lowest possible precedence. Normal function application is left-associative and has highest precedence (10). So $ is something of the opposite.
So then we use it where normal function application or using () doesn't work.
So, for example, this works:
λ> head . sort $ "example"
λ> e
but this does not:
λ> head . sort "example"
because . has lower precedence than sort and the type of (sort "example") is [Char]
λ> :type (sort "example")
(sort "example") :: [Char]
But . expects two functions and there isn't a nice short way to do this because of the order of operations of sort and .
I think a short example of where you would use . and not $ would help clarify things.
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
Note that times6 is a function that is created from function composition.