Haskell Fonction Retour Liste vide
-
27-10-2019 - |
Question
Je suis vraiment un débutant absolu à Haskell, donc je suis à une perte totale quant à la façon de déboguer des fonctions que j'ai écrit. Quand j'appelle shuntingYard ["3+4"]
je reçois []
dos, alors que je veux revenir [34+]
. Toute aide serait grandement, grandement appréciée.
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 []
La solution
En tant que technique de débogage générale, vous pouvez utiliser le module Debug.Trace pour savoir quelles fonctions sont appelées et quelles sont leurs entrées sont. En utilisant regard sur l'état de votre algorithme après chaque étape.
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 -}
Cette impression:
(["3+4"],[])
([],[])
Hmm, vous avez tout perdu après le premier appel. En regardant les gardes __shuntingYard, il semble que le cas « autrement » est appelé.
Peut-être que vous vouliez appeler shuntingYard ["3", "+", "4"]
?
Autres conseils
Ok, let's just play through what happens when you call shuntingYard ["3+4"]
:
- It calls
_shuntingYard ["3+4"] []
- It goes through the guards of
_shuntingYard
:null stmt = null ["3+4"] = false
all isDigit (head stmt) = all isDigit "3+4" = false
as+
is not a digitisOperator (head (head stmt)) = isOperator '3' = false
- Also false as
'3' /= '('
- Also false as
'3' /= ')'
- Since none of the guards matched, so we go into the default case and call
_shuntingYard (tail stmt) stack = _shuntingYard [] []
- This time the first guard(
null stmt = null []
) matches, so we callstackOperations []
and get[]
.