будет иметь тип >IO String
. Какой смысл преобразовывать чистое значение в действие ввода-вывода, которое ничего не делает? Зачем «пачкать» нашу программу больше необходимого? Нам нужно некоторое действие ввода-вывода для второй части условного оператора, чтобы обработать случай пустой строки. Вот для чего мы создали фиктивное действие ввода-вывода, которое ничего не делает, записав >return ()
.
Вызов функции >return
не прекращает выполнение блока >do
– ничего подобного! Например, следующая программа успешно выполнится вся до последней строчки:
>main = do
> return ()
> return "ХА-ХА-ХА"
> line <– getLine
> return "ЛЯ-ЛЯ-ЛЯ"
> return 4
> putStrLn line
Всё, что делает функция >return
, – создаёт действия ввода-вывода, которые не делают ничего, кроме как содержат значения, и все они отбрасываются, поскольку не привязаны к образцам. Мы можем использовать функцию >return
вместе с символом ><–
для того, чтобы связывать значения с образцами.
>main = do
> let a = "ад"
> b = "да!"
> putStrLn $ a ++ " " ++ b
Как вы можете видеть, функция >return
выполняет обратную операцию по отношению к операции ><–
. В то время как функция >return
принимает значение и помещает его в «коробку», операция ><–
принимает (и исполняет) «коробку», а затем привязывает полученное из неё значение к имени. Но всё это выглядит лишним, так как в блоках >do
можно использовать выражение >let
для привязки к именам, например так:
>main = do
> let a = "hell"
> b = "yeah"
> putStrLn $ a ++ " " ++ b
При работе с блоками >do
мы чаще всего используем функцию >return
либо для создания действия ввода-вывода, которое ничего не делает, либо для того, чтобы блок >do
возвращал нужное нам значение, а не результат последнего действия ввода-вывода. Во втором случае мы используем функцию >return
, чтобы создать действие ввода-вывода, которое будет всегда возвращать нужное нам значение, и эта функция >return
должна находиться в самом конце блока >do
.