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

Первые три случая – такие же, как и прежние, только новый стек обёрнут в конструктор >Just (для этого мы использовали здесь функцию >return, но могли и просто написать >Just). В последнем случае мы используем вызов >readMaybe numberString, а затем отображаем это с помощью >(:xs). Поэтому если стек равен >[1.0,2.0], а выражение >readMaybe numberString даёт в результате >Just>3.0, то результатом будет >[3.0,1.0,2.0]. Если же >readMaybe numberString даёт в результате значение >Nothing, результатом будет >Nothing.

Давайте проверим функцию свёртки отдельно:

>ghci> foldingFunction [3,2] "*"

>Just [6.0]

>ghci> foldingFunction [3,2] "-"

>Just [-1.0]

>ghci> foldingFunction [] "*"

>Nothing

>ghci> foldingFunction [] "1"

>Just [1.0]

>ghci> foldingFunction [] "1 уа-уа-уа-уа"

>Nothing

Похоже, она работает! А теперь пришла пора для новой и улучшенной функции >solveRPN. Вот она перед вами, дамы и господа!

>import Data.List


>solveRPN :: String –> Maybe Double

>solveRPN st = do

>   [result] <– foldM foldingFunction [] (words st)

>   return result

Как и в предыдущей версии, мы берём строку и превращаем её в список слов. Затем производим свёртку, начиная с пустого стека, но вместо выполнения обычной свёртки с помощью функции >foldl используем функцию >foldM. Результатом этой свёртки с помощью функции >foldM должно быть значение типа >Maybe, содержащее список (то есть наш окончательный стек), и в этом списке должно быть только одно значение. Мы используем выражение >do, чтобы взять это значение, и называем его >result. В случае если функция >foldM возвращает значение >Nothing, всё будет равно >Nothing, потому что так устроена монада >Maybe. Обратите внимание на то, что мы производим сопоставление с образцом в выражении >do, поэтому если список содержит более одного значения либо ни одного, сопоставление с образцом окончится неудачно и будет произведено значение >Nothing. В последней строке мы просто вызываем выражение >return result, чтобы представить результат вычисления выражения в обратной польской записи как результат окончательного значения типа >Maybe.

Давайте попробуем:

>ghci> solveRPN "1 2 * 4 +"

>Just 6.0

>ghci> solveRPN "1 2 * 4 + 5 *"

>Just 30.0

>ghci> solveRPN "1 2 * 4"

>Nothing

>ghci> solveRPN "1 8 трам-тарарам"

>Nothing

Первая неудача возникает из-за того, что окончательный стек не является списком, содержащим один элемент: в выражении >do сопоставление с образцом терпит фиаско. Вторая неудача возникает потому, что функция >readMaybe возвращает значение >Nothing.

Композиция монадических функций

Когда мы говорили о законах монад в главе 13, вы узнали, что функция