Функция Haskell возвращает пустой список
-
27-10-2019 - |
Вопрос
Я действительно абсолютный новичок в Haskell, поэтому я в полной потери относительно того, как отлаживать некоторые функции, которые я написал. Когда я звоню shuntingYard ["3+4"]
Я вернусь []
, в то время как я хочу вернуться [34+]
. Анкет Любая помощь будет очень ценится.
import Char
isOperator :: Char -> Bool
isOperator x = elem x ['+','-','*','/','%','^','!','=','<','>']
associativityOf :: Char -> String
associativityOf x = if elem x ['+','-','*','/','%']
then "Left"
else "Right"
precedenceOf :: Char -> Int
precedenceOf x
| elem x "=<>" = 1
| elem x "+-" = 2
| elem x "*/%" = 3
| elem x "^!" = 4
| otherwise = 0
operatorActions :: [[Char]] -> [[Char]] -> [[Char]]
operatorActions stmt stack
| ( tokenAssoc == "Left" && tokenPrecedence <= stackPrecedence ) ||
( tokenAssoc == "Right" && tokenPrecedence < stackPrecedence ) =
[stackOper] : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) ((head stmt) : stack)
where tokenAssoc = associativityOf (head (head stmt))
tokenPrecedence = precedenceOf (head (head stmt))
stackOper = if (not (null stack))
then (head (head stack))
else '='
stackPrecedence = precedenceOf stackOper
stackOperations :: [[Char]] -> [[Char]]
stackOperations stack
| ((not (null stack)) && (head (head stack)) == '(') =
error "Unbalanced parens."
| null stack = []
| otherwise = (head stack) : _shuntingYard [] (tail stack)
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack
| null stmt = stackOperations stack
| all isDigit (head stmt) = (head stmt) : _shuntingYard (tail stmt) stack
| isOperator (head (head stmt)) = operatorActions stmt stack
| (head (head stmt)) == '('=
_shuntingYard (tail stmt) ((head stmt) : stack)
| (head (head stmt)) == ')' = if (head (head stack)) == '('
then _shuntingYard (tail stmt) (tail stack)
else (head stack) : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) stack
shuntingYard :: [[Char]] -> [[Char]]
shuntingYard stmt = _shuntingYard stmt []
Решение
В качестве общей техники отладки вы можете использовать модуль Debug.trace, чтобы выяснить, какие функции вызываются и каковы их входные данные. Используя состояние вашего алгоритма после каждого шага.
import Debug.Trace
-- Show arguments each time _shuntingYard is called
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack = traceShow (stmt, stack) $ __shuntingYard stmt stack
__shuntingYard stmt stack
| null stmt = stackOperations stack
{- etcetera -}
Это печатные издания:
(["3+4"],[])
([],[])
Хм, ты потерял все после первого звонка. Глядя на охранников в __shuntingyard, кажется, что случай «в противном случае» называется.
Может ты хотел позвонить shuntingYard ["3", "+", "4"]
?
Другие советы
Хорошо, давайте просто разыграем то, что происходит, когда вы звоните shuntingYard ["3+4"]
:
- Это вызывает
_shuntingYard ["3+4"] []
- Он проходит через охранников
_shuntingYard
:null stmt = null ["3+4"] = false
all isDigit (head stmt) = all isDigit "3+4" = false
в качестве+
не является цифройisOperator (head (head stmt)) = isOperator '3' = false
- Также ложный как
'3' /= '('
- Также ложный как
'3' /= ')'
- Поскольку ни один из охранников не соответствовал, поэтому мы переходим в корпус по умолчанию и вызовываем
_shuntingYard (tail stmt) stack = _shuntingYard [] []
- На этот раз первый охранник (
null stmt = null []
) совпадает, поэтому мы называемstackOperations []
и получить[]
.