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

>solveRPN :: String –> Double

>solveRPN = head . foldl foldingFunction [] . words

>   where foldingFunction stack item = ...

То-то! Намного лучше. Итак, функция для свёртки принимает стек и элемент и возвращает новый стек. Мы будем использовать сопоставление с образцом для того, чтобы получать первые элементы стека, и для сопоставления с операторами, например >* и >–.

>solveRPN :: String –> Double

>solveRPN = head . foldl foldingFunction [] . words

>   where

>      foldingFunction (x:y:ys) "*" = (x * y):ys

>      foldingFunction (x:y:ys) "+" = (x + y):ys

>      foldingFunction (x:y:ys) "–" = (y – x):ys

>      foldingFunction xs numberString = read numberString:xs

Мы уложились в четыре образца. Образцы будут сопоставляться транслятором в порядке записи. Вначале функция свёртки проверит, равен ли текущий элемент >"*". Если да, то функция возьмёт список, например >[3,4,9,3], и присвоит двум первым элементам имена >x и >y соответственно. В нашем случае >x будет соответствовать тройке, а >y – четвёрке; >ys будет равно >[9,3]. В результате будет возвращён список, состоящий из >[9,3], и в качестве первого элемента будет добавлено произведение тройки и четвёрки. Таким образом, мы выталкиваем два первых числа из стека, перемножаем их и помещаем результат обратно в стек. Если элемент не равен >"*", сопоставление с образцом продолжается со следующего элемента, проверяя >"+", и т. д.

Если элемент не совпадёт ни с одним оператором, то мы предполагаем, что это строка, содержащая число. Если это так, то мы вызываем функцию >read с этой строкой, чтобы получить число, добавляем его в вершину предыдущего стека и возвращаем получившийся стек.

Для списка >["2","3","+"] наша функция начнёт свёртку с самого левого элемента. Стек в начале пуст, то есть представляет собой >[]. Функция свёртки будет вызвана с пустым списком в качестве стека (аккумулятора) и >"2" в качестве элемента. Так как этот элемент не является оператором, он будет просто добавлен в начало стека >[]. Новый стек будет равен >[2], функция свёртки будет вызвана со значением >[2] в качестве стека и >"3" в качестве элемента; функция вернёт новый стек, >[3,2]. Затем функция свёртки вызывается в третий раз, со стеком равным >[3,2] и элементом >"+". Это приводит к тому, что оба числа будут вытолкнуты из стека, сложены, а результат будет помещён обратно в стек. Результирующий стек равен >[5] – это число мы вернём.

Погоняем нашу функцию:

>ghci> solveRPN "10 4 3 + 2 * -"

>-4.0

>ghci> solveRPN "2 3.5 +"

>5.5

>ghci> solveRPN "90 34 12 33 55 66 + * - +"

>-3947.0

>ghci> solveRPN "90 34 12 33 55 66 + * - + -"