Version, I think you want:
import Control.Monad (liftM2)
infixl 4 :+:, :-:
infixl 5 :*:, :/:
data Expr a = Const a
| (Expr a) :+: (Expr a)
| (Expr a) :-: (Expr a)
| (Expr a) :*: (Expr a)
| (Expr a) :/: (Expr a)
deriving (Show, Eq)
evalExpr :: (Eq a, Num a, Fractional a) => (Expr a) -> Maybe a
evalExpr (Const a) = return a
evalExpr (a :+: b) = liftM2 (+) (evalExpr a) (evalExpr b)
evalExpr (a :-: b) = liftM2 (-) (evalExpr a) (evalExpr b)
evalExpr (a :*: b) = liftM2 (*) (evalExpr a) (evalExpr b)
evalExpr (a :/: b) = if (evalExpr b) == return 0
then Nothing
else liftM2 (/) (evalExpr a) (evalExpr b)
Changes use the correct monadic (in this case Maybe) type in the case Const( return ainstead of a), and when you check the value 0 ( if (evalExpr b) == return 0rather than if (evalExpr b) == 0).
( , Just, return, Maybe, .)
evalExpr, , . liftM2 Haskell , , , , . , , , Const ==, .
<$> <*> liftM2, :
import Control.Applicative ((<$>), (<*>))
...
evalExpr :: (Eq a, Num a, Fractional a) => (Expr a) -> Maybe a
evalExpr (Const a) = return a
evalExpr (a :+: b) = (+) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :-: b) = (-) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :*: b) = (*) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :/: b) = if (evalExpr b) == return 0
then Nothing
else (/) <$> (evalExpr a) <*> (evalExpr b)
, triad ,
triad <$> arg1 <*> arg2 <*> arg3
. .
@gallais . , , , :
evalExpr :: (Eq a, Num a, Fractional a) => (Expr a) -> Maybe a
evalExpr (Const a) = return a
evalExpr (a :+: b) = (+) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :-: b) = (-) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :*: b) = (*) <$> (evalExpr a) <*> (evalExpr b)
evalExpr (a :/: b) = (/) <$> (evalExpr a) <*> (failOn 0 $ evalExpr b)
failOn x a = case a of
Just x -> Nothing
_ -> a
, MonadZero :
...
evalExpr (a :/: b) = (/) <$> (evalExpr a) <*> (failOn (==0) $ evalExpr b)
failOn f a = do
b <- fmap f a
if b then mzero else a
, , guard, when unless, . .