I've discovered that when doing IO in Haskell, variables that are assigned using the <- operator are only in scope for the statements immediately after them - not in where clauses.
For example:
main :: IO()
main = do
s <- getLine
putStr magic
where
magic = doMagic s
This won't work as s is not in scope. I did some research to confirm it and found this article:
Unlike a let expression where variables are scoped over all definitions, the variables defined by <- are only in scope in the following statements.
So how can I make s available for use in the where clause?
In addition to the general let form, there's a special let form for use with do syntax you can use instead:
main :: IO()
main = do
s <- getLine
let magic = doMagic s
putStr magic
magic is available in all following lines in the block.
Well, magic is a function. Therefore you can do something like:
magic m = doMagic m
Or:
magic = \m-> doMagic m
And call it like so:
putStrLn $ magic s
Of course, as you already researched, the sensible thing to do when you can reuse your computed magic is to use a let ... in expression, and nest the calls:
let magic_str = magic s in
putStrLn magic_str
let is the practical way to handle this. But it may be worth unpacking what's really going on here. The do statement isn't what's causing the scoping trouble.
Remember that
main = do
s <- getLine
putStr magic
where
magic = doMagic s
is equivalent to this:
main = getline >>= \s ->
putStr magic
where magic = doMagic s
If we put in some parentheses, this is:
main = getline >>= (\s -> putStr magic) where magic = doMagic s
This is where the scope of s comes from: it's the argument to a lambda expression, and it only exists within that lambda expression. Try to use it in a where clause outside of that lambda, and you get a "not in scope" error.
let works because let and where parse differently. With parentheses for clarity:
foo = (\x -> let y = x in y) -- Works fine
foo'' = (\x -> y) where y = x -- y is not in scope
This is what's causing the problem; it's not specific to IO, or to do statements.
Related
I'm learning Haskell and having a really hard time with this very simple program:
chooseDifficulty :: IO ()
chooseDifficulty =
do putStrLn "Choose your difficulty:"
putStrLn " 1: easy"
putStrLn " 2: medium"
putStrLn " 3: difficult"
let choice <- getLine
putStrLn "Choice was " ++ choice
main :: IO ()
main = chooseDifficulty
I'm having the error "parse error on input ‘<-’ Perhaps this statement should be within a 'do' block?" on line 7. I've tried all sorts of formatting but haven't been able to fix that since it's in a do block already.
Haskell's do syntax has the following features:
1.
do
...
action -- e.g. putStrLn "bla"
moreStuff
Simply executes the action (i.e. binding it into the monad), discards any results, and doesn't introduce new variables. Under the hood this uses the >> operator to sequence action before everything that comes afterwards, action >> moreStuff.
2.
do
...
let v = 37
moreStuff
This doesn't really have anything to do with monadic actions, it's just a slightly different way of writing the standard let:
do
...
let v = 37 in moreStuff
or
do
...
let v = 37
in do
moreStuff
Note that this only works with “pure values” like numbers; it would be no use to write something like let v = getLine because this wouldn't actually invoke the action, only give a new name to it.
3.
do
...
y <- resultfulAction -- e.g. getLine
moreStuff
No let in this one. This executes the action and binds its result in the variable y. Under the hood it uses the >>= operator, namely resultfulAction >>= \y -> moreStuff.
If Haskell is lazy, why does getLine is evaluated in both of the following cases? Being lazy I would expect that in the case of fa the getLine would not be evaluated because its result is not being used subsequently:
let fa = do {
x <- getLine;
return "hello"
}
let fb = do {
x <- getLine;
return $ x
}
(I tested both cases in GHCi)
Thanks
Its result is being used, just not in the way you necessarily expect. This de-sugars to
fa = getLine >>= (\x -> return "hello")
So the result of getLine is still passed to the function \x -> return "hello". Monads are inherently about sequencing actions together (among other things); that sequencing still occurs even if results are later not used. If that weren't the case, then
main = do
print "Hello"
print "World"
wouldn't do anything as a program, since the results of both calls to print aren't being used.
Congratulations, you've just discovered why Haskell is a pure functional language!
The result† of getLine is not a string. It's an IO action which happens to “produce” a string. That string is indeed not evaluated, but the action itself is (since it turns up in a do block bound to main), and this is all that matters as far as side-effects are concerned.
†Really just the value of getLine. This is not a function, so it doesn't actually have a result.
Be careful now... ;-)
The result of getLine isn't a string, it's an "I/O command object", if you will. The code actually desugars to
getLine >>= (\ x -> return "hello")
The >>= operator constructs a new I/O command object out of an existing one and a function... OK, that's a bit much to wrap your mind around. The important thing is, the I/O action gets executed (because of the implementation of >>= for IO), but its result doesn't necessarily get evaluated (because of laziness).
So let's look at the implementation of the IO monad... erm, actually you know what? Let's not. (It's deep magic, hard-wired into the compiler, and as such it's implementation-specific.) But this phenomenon isn't unique to IO by any means. Let's look at the Maybe monad:
instance Monad Maybe where
mx >>= f =
case mx of
Nothing -> Nothing
Just x -> f x
return x = Just x
So if I do something like
do
x <- foobar
return "hello"
Will x get evaluated? Let's look. It desugars to:
foobar >>= (\ x -> return "hello")
then this becomes
case foobar of
Nothing -> Nothing
Just x -> Just "hello"
As you can see, foobar is clearly going to be evaluated, because we need to know whether the result is Nothing or Just. But the actual x won't be evaluated, because nothing looks at it.
It's kind of the same way that length evaluates the list nodes, but not the list elements they point to.
I am lost in this concept. This is my code and what it does is just asking what is your name.
askName = do
name <- getLine
return ()
main :: IO ()
main = do
putStrLn "Greetings once again. What is your name?"
askName
However, How can I access in my main the variable name taken in askName?
This is my second attempt:
askUserName = do
putStrLn "Hello, what's your name?"
name <- getLine
return name
sayHelloUser name = do
putStrLn ("Hey " ++ name ++ ", you rock!")
main = do
askUserName >>= sayHelloUser
I can now re-use the name in a callback way, however if in main I want to call name again, how can I do that? (avoiding to put name <- getLine in the main, obviously)
We can imagine that you ask the name in order to print it, then let's rewrite it.
In pseudo code, we have
main =
print "what is your name"
bind varname with userReponse
print varname
Your question then concern the second instruction.
Take a look about the semantic of this one.
userReponse is a function which return the user input (getLine)
varname is a var
bind var with fun : is a function which associate a var(varname) to the output of a function(getLine)
Or as you know in haskell everything is a function then our semantic is not well suited.
We need to revisit it in order to respect this idiom. According to the later reflexion the semantic of our bind function become bind fun with fun
As we cannot have variable, to pass argument to a function, we need, at a first glance, to call another function, in order to produce them. Thus we need a way to chain two functions, and it's exactly what's bind is supposed to do. Furthermore, as our example suggest, an evaluation order should be respected and this lead us to the following rewriting with fun bind fun
That's suggest that bind is more that a function it's an operator.
Then for all function f and g we have with f bind g.
In haskell we note this as follow
f >>= g
Furthermore, as we know that a function take 0, 1 or more argument and return 0, 1 or more argument.
We could refine our definition of our bind operator.
In fact when f doesn't return any result we note >>= as >>
Applying, theses reflexions to our pseudo code lead us to
main = print "what's your name" >> getLine >>= print
Wait a minute, How the bind operator differ from the dot operator use for the composition of two function ?
It's differ a lot, because we have omit an important information, bind doesn't chain two function but it's chain two computations unit. And that's the whole point to understand why we have define this operator.
Let's write down a global computation as a sequence of computation unit.
f0 >>= f1 >> f2 >> f3 ... >>= fn
As this stage a global computation could be define as a set of computation unit with two operator >>=, >>.
How do we represent set in computer science ?
Usually as container.
Then a global computation is a container which contain some computation unit. On this container we could define some operator allowing us to move from a computation unit to the next one, taking into account or not the result of the later, this is ours >>= and >> operator.
As it's a container we need a way to inject value into it, this is done by the return function. Which take an object and inject it into a computation, you could check it through is signature.
return :: a -> m a -- m symbolize the container, then the global computation
As it's a computation we need a way to manage a failure, this done by the fail function.
In fact the interface of a computation is define by a class
class Computation
return -- inject an objet into a computation
>>= -- chain two computation
>> -- chain two computation, omitting the result of the first one
fail -- manage a computation failure
Now we can refine our code as follow
main :: IO ()
main = return "What's your name" >>= print >> getLine >>= print
Here I have intentionally include the signature of the main function, to express the fact that we are in the global IO computation and the resulting output with be () (as an exercise enter $ :t print in ghci).
If we take more focus on the definition for >>=, we can emerge the following syntax
f >>= g <=> f >>= (\x -> g) and f >> g <=> f >>= (\_ -> g)
And then write
main :: IO ()
main =
return "what's your name" >>= \x ->
print x >>= \_ ->
getLine >>= \x ->
print x
As you should suspect, we certainly have a special syntax to deal with bind operator in computational environment. You're right this is the purpose of do syntax
Then our previous code become, with do syntax
main :: IO ()
main = do
x <- return "what's your name"
_ <- print x
x <- getLine
print x
If you want to know more take a look on monad
As mentioned by leftaroundabout, my initial conclusion was a bit too enthusiastic
You should be shocked, because we have break referential transparency law (x take two different value inside our sequence of instruction), but it doesn't matter anymore,because we are into a computation, and a computation as defined later is a container from which we can derive an interface and this interface is designed to manage, as explain, the impure world which correspond to the real world.
Return the name from askname. In Haskell its not idiomatic to access "global" variables:
askName :: IO String
askName = do
name <- getLine
return name
main :: IO ()
main = do
putStrLn "Greetings once again. What is your name?"
name <- askName
putStrLn name
Now the only problem is tht the askName function is kind of pointless, since its now just an alias to getLine. We could "fix" that by putting the question inside askName:
askName :: IO String
askName = do
putStrLn "Greetings once again. What is your name?"
name <- getLine
return name
main :: IO ()
main = do
name <- askName
putStrLn name
Finally, just two little points: its usually a good idea to put type declarations when you are learning, to make things explicit and help compiler error messages. Another thing is to remember that the "return" function is only used for monadic code (it is not analogous to a traditional return statement!) and sometimes we could have ommited some intermediary variables:
askName :: IO String
askName = do
putStrLn "Greetings once again. What is your name?"
getLine
I have a hard time grasping this. When writing in do notation, how are the following two lines different?
1. let x = expression
2. x <- expression
I can't see it. Sometimes one works, some times the other. But rarely both. "Learn you a haskell" says that <- binds the right side to the symbol on the left. But how is that different from simply defining x with let?
The <- statement will extract the value from a monad, and the let statement will not.
import Data.Typeable
readInt :: String -> IO Int
readInt s = do
putStrLn $ "Enter value for " ++ s ++ ": "
readLn
main = do
x <- readInt "x"
let y = readInt "y"
putStrLn $ "x :: " ++ show (typeOf x)
putStrLn $ "y :: " ++ show (typeOf y)
When run, the program will ask for the value of x, because the monadic action readInt "x" is executed by the <- statement. It will not ask for the value of y, because readInt "y" is evaluated but the resulting monadic action is not executed.
Enter value for x:
123
x :: Int
y :: IO Int
Since x :: Int, you can do normal Int things with it.
putStrLn $ "x = " ++ show x
putStrLn $ "x * 2 = " ++ show (x * 2)
Since y :: IO Int, you can't pretend that it's a regular Int.
putStrLn $ "y = " ++ show y -- ERROR
putStrLn $ "y * 2 = " ++ show (y * 2) -- ERROR
In a let binding, the expression can have any type, and all you're doing is giving it a name (or pattern matching on its internal structure).
In the <- version, the expression must have type m a, where m is whatever monad the do block is in. So in the IO monad, for instance, bindings of this form must have some value of type IO a on the right-hand side. The a part (inside the monadic value) is what is bound to the pattern on the left-hand side. This lets you extract the "contents" of the monad within the limited scope of the do block.
The do notation is, as you may have read, just syntactic sugar over the monadic binding operators (>>= and >>). x <- expression de-sugars to expression >>= \x -> and expression (by itself, without the <-) de-sugars to expression >>. This just gives a more convenient syntax for defining long chains of monadic computations, which otherwise tend to build up a rather impressive mass of nested lambdas.
let bindings don't de-sugar at all, really. The only difference between let in a do block and let outside of a do block is that the do version doesn't require the in keyword to follow it; the names it binds are implicitly in scope for the rest of the do block.
In the let form, the expression is a non-monadic value, while the right side of a <- is a monadic expression. For example, you can only have an I/O operation (of type IO t) in the second kind of binding. In detail, the two forms can be roughly translated as (where ==> shows the translation):
do {let x = expression; rest} ==> let x = expression in do {rest}
and
do {x <- operation; rest} ==> operation >>= (\ x -> do {rest})
let just assigns a name to, or pattern matches on arbitrary values.
For <-, let us first step away from the (not really) mysterious IO monad, but consider monads that have a notion of a "container", like a list or Maybe. Then <- does not more than "unpacking" the elements of that container. The opposite operation of "putting it back" is return. Consider this code:
add m1 m2 = do
v1 <- m1
v2 <- m2
return (v1 + v2)
It "unpacks" the elements of two containers, add the values together, and wraps it again in the same monad. It works with lists, taking all possible combinations of elements:
main = print $ add [1, 2, 3] [40, 50]
--[41,51,42,52,43,53]
In fact in case of lists you could write as well add m1 m2 = [v1 + v2 | v1 <- m1, v2 <- m2]. But our version works with Maybes, too:
main = print $ add (Just 3) (Just 12)
--Just 15
main = print $ add (Just 3) Nothing
--Nothing
Now IO isn't that different at all. It's a container for a single value, but it's a "dangerous" impure value like a virus, that we must not touch directly. The do-Block is here our glass containment, and the <- are the built-in "gloves" to manipulate the things inside. With the return we deliver the full, intact container (and not just the dangerous content), when we are ready. By the way, the add function works with IO values (that we got from a file or the command line or a random generator...) as well.
Haskell reconciles side-effectful imperative programming with pure functional programming by representing imperative actions with types of form IO a: the type of an imperative action that produces a result of type a.
One of the consequences of this is that binding a variable to the value of an expression and binding it to the result of executing an action are two different things:
x <- action -- execute action and bind x to the result; may cause effect
let x = expression -- bind x to the value of the expression; no side effects
So getLine :: IO String is an action, which means it must be used like this:
do line <- getLine -- side effect: read from stdin
-- ...do stuff with line
Whereas line1 ++ line2 :: String is a pure expression, and must be used with let:
do line1 <- getLine -- executes an action
line2 <- getLine -- executes an action
let joined = line1 ++ line2 -- pure calculation; no action is executed
return joined
Here is a simple example showing you the difference.
Consider the two following simple expressions:
letExpression = 2
bindExpression = Just 2
The information you are trying to retrieve is the number 2.
Here is how you do it:
let x = letExpression
x <- bindExpression
let directly puts the value 2 in x.
<- extracts the value 2 from the Just and puts it in x.
You can see with that example, why these two notations are not interchangeable:
let x = bindExpression would directly put the value Just 2 in x.
x <- letExpression would not have anything to extract and put in x.
I know that the following "do" notation's "bind" function is equivalent to getLine >>= \line -> putStrLn
do line <- getLine
putStrLn line
But how is the following notation equivalent to bind function?
do line1 <- getLine
putStrLn "enter second line"
line2 <- getLine
return (line1,line2)
I take it you are trying to see how to bind the result of "putStrLn". The answer is in the type of putStrLn:
putStrLn :: String -> IO ()
Remember that "()" is the unit type, which has a single value (also written "()"). So you can bind this in exactly the same way. But since you don't use it you bind it to a "don't care" value:
getLine >>= \line1 ->
putStrLn "enter second line" >>= \_ ->
getline >>= \line2 ->
return (line1, line2)
As it happens, there is an operator already defined for ignoring the return value, ">>". So you could just rewrite this as
getLine >>= \line1 ->
putStrLn "enter second line" >>
getline >>= \line2 ->
return (line1, line2)
I'm not sure if you are also trying to understand how bind operators are daisy-chained. To see this, let me put the implicit brackets and extra indentation in the example above:
getLine >>= (\line1 ->
putStrLn "enter second line" >> (
getline >>= (\line2 ->
return (line1, line2))))
Each bind operator links the value to the left with a function to the right. That function consists of all the rest of the lines in the "do" clause. So the variable being bound through the lambda ("line1" in the first line) is in scope for the whole of the rest of the clause.
For this specific example you can actually avoid both do and >>= by using combinators from Control.Applicative:
module Main where
import Control.Applicative ((<$>), (<*>), (<*))
getInput :: IO (String, String)
getInput = (,) <$> getLine <* putStrLn "enter second line" <*> getLine
main = print =<< getInput
Which works as expected:
travis#sidmouth% ./Main
hello
enter second line
world
("hello","world")
It looks a little weird at first, but in my opinion the applicative style feels very natural once you're used to it.
I would strongly suggest you to read the chapter Desugaring of Do-blocks in the book Real-World haskell. It tells you, that you all are wrong. For a programmer, it's the natural way to use a lambda, but the do-block is implemented using functions which - if a pattern maching failuire occurs - will call the fail implementation of the according monad.
For instance, your case is like:
let f x =
putStrLn "enter second line" >>
let g y = return (x,y)
g _ = fail "Pattern mismatched"
in getLine >>= g
f _ = fail "Pattern mismatched"
in getLine >>= f
In a case like this, this may be completely irrelevant. But consider some expression that involves pattern-matching. Also, you can use this effect for some special stuff, eg, you can do something like this:
oddFunction :: Integral a => [a] -> [a]
oddFunctiond list = do
(True,y) <- zip (map odd list) list
return y
What will this function do? You can read this statement as a rule for working with the elements of the list. The first statement binds an element of the list to the var y, but only if y is odd. If y is even, a pattern matching failure occurs and fail will be called. In the monad instance for Lists, fail is simply []. Thus, the function strips all even elements from the list.
(I know, oddFunction = filter odd would do this better, but this is just an example)
getLine >>= \line1 ->
putStrLn "enter second line" >>
getLine >>= \line2 ->
return (line1, line2)
Generally foo <- bar becomes bar >>= \foo -> and baz becomes baz >> (unless it's the last line of the do-block, in which case it just stays baz).