So we have following Data Types:
data Expr = Num Double | Add Expr Expr | Var Char deriving Show
and
type Env = [(Char, Double)]
Further More we have these two functions:
evalDo :: Env -> Expr -> Maybe Double evalDo _ (Num a) = return a evalDo e (Var c) = getvar e c evalDo e (Add a b) = do a' <- evalDo e a b' <- evalDo e b Just (a'+b') and
getvar :: Env -> Char -> Maybe Double getvar [] c = Nothing getvar ((x,y):es) c | c == x = Just y |otherwise = getvar es c So if we would run the following Code: evalDo [('x', 2)] (Add (Num 5) (Var 'x')), we would receive:Just 7.0. Whereas evalDo [('x', 2)] (Add (Num 5) (Var 'y')) evaluates to Nothing.
From what I understand when running the former code, our function matches the evalDo e (Var c) = getvar e c line. From there it calls getvar e c which results in Just 2. Then we go back to our original second call, which is (Add (Num 5) (Var 'x'))
. Now the Var 'x' is resolved into Just 2. So finally the evalDo e (Add a b) = do... function-line matches and we get Just7.0.
Obviously there is a huge major flaw to my explanation, since we try to "Add" Num 5 and Just 2 and by our definition its not possible. Yet the function seems to work flawelessly somehow but I just can't figure it out.
evalDo e (Add a b) = liftA2 (+) (evalDo e a) (evalDo e b). Or the alternative with punctuation instead of parens:evalDo e (Add a b) = (+) <$> evalDo e a <*> evalDo e b.