Изучай Haskell во имя добра! (Липовача) - страница 229

>Just "3!"

Это мы уже проходили! Передача монадического значения функции, которая возвращает монадическое значение, – ничего особенного. Заметьте, как параметр >x становится равным значению >3 внутри анонимной функции, когда мы выполняем код. Как только мы внутри этой анонимной функции, это просто обычное значение, а не монадическое. А что если бы у нас был ещё один вызов оператора >>>= внутри этой функции? Посмотрите:

>ghci> Just 3 >>= (\x –> Just "!" >>= (\y –> Just (show x ++ y)))

>Just "3!"

Ага-а, вложенное использование операции >>>=! Во внешней анонимной функции мы передаём значение >Just "!" анонимной функции >\y –> Just (show x ++ y). Внутри этой анонимной функции параметр >y становится равным >"!". Параметр >x по-прежнему равен >3, потому что мы получили его из внешней анонимной функции. Всё это как будто напоминает мне о следующем выражении:

>ghci> let x = 3; y = "!" in show x ++ y

>"3!"

Главное отличие состоит в том, что значения в нашем примере с использованием оператора >>>= являются монадическими. Это значения с контекстом неудачи. Мы можем заменить любое из них на неудачу:

>ghci> Nothing >>= (\x –> Just "!" >>= (\y –> Just (show x ++ y))) Nothing

>ghci> Just 3 >>= (\x –> Nothing >>= (\y –> Just (show x ++ y)))

>Nothing

>ghci> Just 3 >>= (\x –> Just "!" >>= (\y –> Nothing))

>Nothing

В первой строке передача значения >Nothing функции естественным образом даёт в результате >Nothing. Во второй строке мы передаём значение >Just 3 функции, и параметр >x становится равным >3. Но потом мы передаём значение >Nothing внутренней анонимной функции, и результатом становится >Nothing, что заставляет внешнюю анонимную функцию тоже произвести >Nothing в качестве своего результата. Это что-то вроде присвоения значений переменным в выражениях >let, только значения, о которых идёт речь, являются монадическими.

Чтобы проиллюстрировать эту идею, давайте запишем следующие строки в сценарий так, чтобы каждое значение типа >Maybe занимало свою собственную строку:

>foo :: Maybe String

>foo = Just 3 >>= (\x –>

>      Just "!">>= (\y –>

>      Just (show x ++ y)))

Чтобы уберечь нас от написания всех этих раздражающих анонимных функций, язык Haskell предоставляет нам нотацию >do. Она позволяет нам записать предыдущий кусок кода вот так:

>foo :: Maybe String

>foo = do

>    x <– Just 3

>    y <– Just "!"

>    Just (show x ++ y)

Могло показаться, что мы получили возможность временно извлекать сущности из значений типа >Maybe без необходимости проверять на каждом шагу, являются ли значения типа >Maybe значениями в конструкторе >Just или значениями