```main = do
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
```

• 在屏幕上打印字符串
• 從鍵盤上讀取字符串
• 向文件寫入數據
• 從文件中讀取數據

## 動作(Actions)

```putStrLn :: String -> IO ()
```

 註解 實際上這個類型說明`putStrLn`是一個「IO monad"中的動作, 但是目前我們會先忽略它。

```getLine :: IO String
```

However, while you are not allowed to run actions yourself, you are allowed to `combine` actions. There are two ways to go about this. The one we will focus on in this chapter is the do notation, which provides a convenient means of putting actions together, and allows us to get useful things done in Haskell without having to understand what really happens. Lurking behind the do notation is the more explicit approach using the (>>=) operator, but we will not be ready to cover this until the chapter Understanding monads

 註解 Do notation is just syntactic sugar for `(>>=)`. If you have experience with higher order functions, it might be worth starting with the latter approach and coming back here to see how do notation gets used. 實際上do是`(>>=)`的語法糖。如果你有使用高階函數的經驗，可以直接閱讀學習第二種方法然後回來這章學習如何使用do

Let's consider the following name program:

```main = do
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
```

We can consider the do notation as a way to combine a sequence of actions. Moreover, the `<-` notation is a way to get the value out of an action. So, in this program, we're sequencing three actions: a `putStrLn`, a `getLine` and another `putStrLn`. The `putStrLn` action has type `String -> IO ()`, so we provide it a `String`, so the fully applied action has type `IO ()`. This is something that we are allowed to run as a program.

Write a program which asks the user for the base and height of a triangle, calculates its area and prints it to the screen. The interaction should look something like:

```The base?
3.3
The height?
5.4
The area of that triangle is 8.91
```
Hint: you can use the function `read` to convert user strings like "3.3" into numbers like 3.3 and function `show` to convert a number into string.

### Left arrow clarifications

#### The `<-` is optional

While we are allowed to get a value out of certain actions like `getLine`, we certainly are not obliged to do so. For example, we could very well have written something like this:

```main = do
getLine
putStrLn ("Hello, how are you?")
```

Clearly, that isn't very useful: the whole point of prompting the user for his or her name was so that we could do something with the result. That being said, it is conceivable that one might wish to read a line and completely ignore the result. Omitting the `<-` will allow for that; the action will happen, but the data won't be stored anywhere.

In order to get the value out of the action, we write `name <- getLine`, which basically means "run `getLine`, and put the results in the variable called `name`."

#### The `<-` can be used with any action (except the last)

On the flip side, there are also very few restrictions which actions can have values obtained from them. Consider the following example, where we put the results of each action into a variable (except the last... more on that later):

```main = do
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
```

The variable `x` gets the value out of its action, but that isn't very interesting because the action returns the unit value `()`. So while we could technically get the value out of any action, it isn't always worth it. But wait, what about that last action? Why can't we get a value out of that? Let's see what happens when we try:

```main = do
name <- getLine
y <- putStrLn ("Hello, " ++ name ++ ", how are you?")
```

Whoops!

```YourName.hs:5:2:
The last statement in a 'do' construct must be an expression
```

This is a much more interesting example, but it requires a somewhat deeper understanding of Haskell than we currently have. Suffice it to say, whenever you use `<-` to get the value of an action, Haskell is always expecting another action to follow it. So the very last action better not have any `<-`s.

### Controlling actions

Normal Haskell constructions like if/then/else and case/of can be used within the do notation, but you need to be somewhat careful. For instance, in a simple "guess the number" program, we have:

```    doGuessing num = do
guess <- getLine
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else do putStrLn "You Win!"
```

If we think about how the if/then/else construction works, it essentially takes three arguments: the condition, the "then" branch, and the "else" branch. The condition needs to have type `Bool`, and the two branches can have any type, provided that they have the same type. The type of the entire if/then/else construction is then the type of the two branches.

In the outermost comparison, we have `(read guess) < num` as the condition. This clearly has the correct type. Let's just consider the "then" branch. The code here is:

```              do putStrLn "Too low!"
doGuessing num
```

Here, we are sequencing two actions: `putStrLn` and `doGuessing`. The first has type `IO ()`, which is fine. The second also has type `IO ()`, which is fine. The type result of the entire computation is precisely the type of the final computation. Thus, the type of the "then" branch is also `IO ()`. A similar argument shows that the type of the "else" branch is also `IO ()`. This means the type of the entire if/then/else construction is `IO ()`, which is just what we want.

 註解 In this code, the last line is `else do putStrLn "You Win!"`. This is somewhat overly verbose. In fact, ```else putStrLn "You Win!"``` would have been sufficient, since do is only necessary to sequence actions. Since we have only one action here, it is superfluous.

It is incorrect to think to yourself "Well, I already started a do block; I don't need another one," and hence write something like:

```    do if (read guess) < num
then putStrLn "Too low!"
doGuessing num
else ...
```

Here, since we didn't repeat the do, the compiler doesn't know that the `putStrLn` and `doGuessing` calls are supposed to be sequenced, and the compiler will think you're trying to call `putStrLn` with three arguments: the string, the function `doGuessing` and the integer `num`. It will certainly complain (though the error may be somewhat difficult to comprehend at this point).

We can write the same `doGuessing` function using a case statement. To do this, we first introduce the Prelude function `compare`, which takes two values of the same type (in the `Ord` class) and returns one of `GT`, `LT`, `EQ`, depending on whether the first is greater than, less than or equal to the second.

```doGuessing num = do
guess <- getLine
case compare (read guess) num of
LT -> do putStrLn "Too low!"
doGuessing num
GT -> do putStrLn "Too high!"
doGuessing num
EQ -> do putStrLn "You Win!"
```

Here, again, the dos after the `->`s are necessary on the first two options, because we are sequencing actions.

If you're used to programming in an imperative language like C or Java, you might think that return will exit you from the current function. This is not so in Haskell. In Haskell, return simply takes a normal value (for instance, one of type `Int`) and makes it into an action that returns the given value (for the same example, the action would be of type `IO Int`). In particular, in an imperative language, you might write this function as:

```void doGuessing(int num) {
if (guess == num) {
print "You win!";
return ();
}

// we won't get here if guess == num
if (guess < num) {
print "Too low!";
doGuessing(num);
} else {
print "Too high!";
doGuessing(num);
}
}
```

Here, because we have the `return ()` in the first `if` match, we expect the code to exit there (and in most imperative languages, it does). However, the equivalent code in Haskell, which might look something like:

```doGuessing num = do
guess <- getLine
case compare (read guess) num of
EQ -> do putStrLn "You win!"
return ()

-- we don't expect to get here if guess == num
then do print "Too low!";
doGuessing num
else do print "Too high!";
doGuessing num
```

First of all, if you guess correctly, it will first print "You win!," but it won't exit, and it will check whether `guess` is less than `num`. Of course it is not, so the else branch is taken, and it will print "Too high!" and then ask you to guess again.

On the other hand, if you guess incorrectly, it will try to evaluate the case statement and get either `LT` or `GT` as the result of the `compare`. In either case, it won't have a pattern that matches, and the program will fail immediately with an exception.

What does the following program print out?

```main =
do x <- getX
putStrLn x

getX =
do return "hello"
return "aren't"
return "these"
return "returns"
return "rather"
return "pointless?"
```
Why?

Write a program that asks the user for his or her name. If the name is one of Simon, John or Phil, tell the user that you think Haskell is a great programming language. If the name is Koen, tell them that you think debugging Haskell is fun (Koen Classen is one of the people who works on Haskell debugging); otherwise, tell the user that you don't know who he or she is.

Write two different versions of this program, one using if

statements, the other using a case statement.

## Actions under the microscope

Actions may look easy up to now, but they are actually a common stumbling block for new Haskellers. If you have run into trouble working with actions, you might consider looking to see if one of your problems or questions matches the cases below. It might be worth skimming this section now, and coming back to it when you actually experience trouble.

One temptation might be to simplify our program for getting a name and printing it back out. Here is one unsuccessful attempt:

```main =
do putStrLn "What is your name? "
putStrLn ("Hello " ++ getLine)
```

Ouch!

```YourName.hs:3:26:
Couldn't match expected type `[Char]'
against inferred type `IO String'
```

Let us boil the example above down to its simplest form. Would you expect this program to compile?

```main =
do putStrLn getLine
```

For the most part, this is the same (attempted) program, except that we've stripped off the superflous "What is your name" prompt as well as the polite "Hello". One trick to understanding this is to reason about it in terms of types. Let us compare:

```putStrLn :: String -> IO ()
getLine  :: IO String
```

We can use the same mental machinery we learned in Type basics to figure how everything went wrong. Simply put, putStrLn is expecting a `String` as input. We do not have a `String`, but something tantalisingly close, an `IO String`. This represents an action that will give us a `String` when it's run. To obtain the `String` that `putStrLn` wants, we need to run the action, and we do that with the ever-handy left arrow, `<-`.

```main =
do name <- getLine
putStrLn name
```

Working our way back up to the fancy example:

```main =
do putStrLn "What is your name? "
name <- getLine
putStrLn ("Hello " ++ name)
```

Now the name is the String we are looking for and everything is rolling again.

### Mind your expression types too

Fine, so we've made a big deal out of the idea that you can't use actions in situations that don't call for them. The converse of this is that you can't use non-actions in situations that DO expect actions. Say we want to greet the user, but this time we're so excited to meet them, we just have to SHOUT their name out:

```import Data.Char (toUpper)

main =
do name <- getLine
loudName <- makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)

makeLoud :: String -> String
makeLoud s = map toUpper s
```
This goes wrong...
```    Couldn't match expected type `IO' against inferred type `[]'
Expected type: IO t
Inferred type: String
In a 'do' expression: loudName <- makeLoud name
```

This is quite similar to the problem we ran into above: we've got a mismatch between something that is expecting an IO type, and something which is not. This time, the cause is our use of the left arrow `<-`; we're trying to left arrow a value of `makeLoud name`, which really isn't left arrow material. It's basically the same mismatch we saw in the previous section, except now we're trying to use regular old String (the loud name) as an IO String, which clearly are not the same thing. The latter is an action, something to be run, whereas the former is just an expression minding its own business. Note that we cannot simply use `loudName = makeLoud name` because a `do` sequences actions, and `loudName = makeLoud name` is not an action.

So how do we extricate ourselves from this mess? We have a number of options:

• We could find a way to turn `makeLoud` into an action, to make it return `IO String`. But this is not desirable, because the whole point of functional programming is to cleanly separate our side-effecting stuff (actions) from the pure and simple stuff. For example, what if we wanted to use makeLoud from some other, non-IO, function? An IO `makeLoud` is certainly possible (how?), but missing the point entirely.
• We could use `return` to promote the loud name into an action, writing something like `loudName <- return (makeLoud name)`. This is slightly better, in that we are at least leaving the `makeLoud` itself function nice and IO-free, whilst using it in an IO-compatible fashion. But it's still moderately clunky, because by virtue of left arrow, we're implying that there's action to be had -- how exciting! -- only to let our reader down with a somewhat anticlimatic `return`
• Or we could use a let binding...

It turns out that Haskell has a special extra-convenient syntax for let bindings in actions. It looks a little like this:

```main =
do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
```

If you're paying attention, you might notice that the let binding above is missing an `in`. This is because `let` bindings in `do` blocks do not require the `in` keyword. You could very well use it, but then you'd have to make a mess of your do blocks. For what it's worth, the following two blocks of code are equivalent.

sweet unsweet
``` do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
```
``` do name <- getLine
let loudName = makeLoud name
in  do putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
```

1. Why does the unsweet version of the let binding require an extra `do` keyword?
2. Do you always need the extra `do`?
3. (extra credit) Curiously, `let` without `in` is exactly how we wrote things when we were playing with the interpreter in the beginning of this book. Why can you omit the `in` keyword in the interpreter, when you'd have to put it in when typing up a source file?