少なくとも、私はそれが起こっていると思います。間違ったモナドで処理が失敗する
Main.hs:
module Main (
main
) where
import Arithmetic
import Data.Maybe
import Data.Either
import Control.Monad.Error
testExpr :: Expr Float
testExpr =
(MultExpr "*"
(AddExpr "XXX"
(NumExpr 1)
(AddExpr "-"
(NumExpr 24)
(NumExpr 21)
)
)
(NumExpr 5)
)
main :: IO()
main = do
putStrLn $ case eval testExpr of
Left msg -> "Error: " ++ msg
Right result -> show result
Arithmetic.hs:
{-# LANGUAGE GADTs #-}
module Arithmetic where
type Op = String
data Expr a where
NumExpr :: Float -> Expr Float
AddExpr :: Op -> Expr Float -> Expr Float -> Expr Float
MultExpr :: Op -> Expr Float -> Expr Float -> Expr Float
eval :: (Monad m) => Expr Float -> m Float
eval (NumExpr n) = return n
eval (AddExpr "+" e1 e2) = evalBin (+) e1 e2
eval (AddExpr "-" e1 e2) = evalBin (-) e1 e2
eval (AddExpr "%" e1 e2) = evalBin (%) e1 e2
eval (AddExpr _ _ _) = fail "Invalid operator. Expected +, - or %"
eval (MultExpr "*" e1 e2) = evalBin (*) e1 e2
eval (MultExpr "/" e1 e2) = evalBin (/) e1 e2
eval (MultExpr _ _ _) = fail "Invalid operator. Expected * or /"
evalBin :: (Monad m) => (Float -> Float -> Float) -> Expr Float -> Expr Float -> m Float
evalBin op e1 e2 = do
v1 <- eval e1
v2 <- eval e2
return $ op v1 v2
infixl 6 %
(%) :: Float -> Float -> Float
a % b = a - b * (fromIntegral $ floor (a/b))
しかし、eval
が失敗したときに、私が "エラー:" せずに、IOでエラーが出るの文字列が追加されます。
ここで紹介したコードではこれは不可能です。 'eval testExpr'は' Either'モナドで評価され、決して 'IO'の近くにはありません。省略したコードに何か間違っている必要があります。たとえば、評価コードの別の部分が直接的または間接的に「エラー」を呼び出す可能性があり、IO例外としてバブルアップします。 – ehird
ありがとう、私は完全なコードで投稿を更新しました –
問題は元のコードでも見えていたことが分かりました。私は修正を投稿しました:) – ehird