2016-04-28 6 views
2

Ich schreibe einen Interpreter in Haskell und ich habe map: name_of_function -> definition of function.Wie man "case" vermeiden kann, wenn man `Maybe` behandelt

Map String Defun 

Mein Dolmetscher Monade:

type InterpreterMonad = StateT (EnvFun, (Stack EnvEval)) (ErrorT String IO)() 

Und wie können Sie "letzte" Monade sehen ist ErroT.

Nun, wenn ich handle Aufruf von Funktionen würden:

handleFCall :: Stmt -> InterpreterMonad 
    handleFCall (VarName name) args = get >>= \(envFun, contextStack) -> case (Map.lookup (VarName name) envFun) of 
     Nothing -> throwError "Err" 
     (Just x) -> DoSthOther 

Und wie man sehen kann ich case verwenden. Jedoch verwende ich >>=, also möchte ich case of hier vermeiden. Aber, Map.lookup zurück Nothing auf Fehler und ich möchte meine Fehlermeldung hinzufügen.

Ich habe keine Erfahrung in Haskell, also weiß ich nicht, wie man damit umgeht. Darüber hinaus ist jede Kritik an meinem Code willkommen.

Prost.

Antwort

4

Es ist nichts falsch mit einer Case-Anweisung verwenden, obwohl umformatiert mit Ihrer Funktion mehr aussehen würden Sie Notation wie

handleFCall (VarName name) args = do 
    (envFun, contextStack) <- get 
    case Map.lookup (VarName name) envFun of 
     Nothing -> throwError "Err" 
     Just x -> doSthOther x 

Welche vertrauten andere Haskell Programmierer sein würde. Wenn Sie jedoch wirklich mit einem Fall vermeiden wollen, benutzen Sie einfach die maybe Funktion:

handleFCall (VarName name) args = do 
    (envFun, contextStack) <- get 
    maybe (throwError "Err") doSthOther $ Map.lookup (VarName name) envFun 

Oder mit >>=

handleFCall (VarName name) args 
    = get >>= 
     (\(envFun, contextStack) -> 
      maybe (throwError "Err") doSthOther 
       $ Map.lookup (VarName name) envFun 
     ) 

Aber ich persönlich finde die Aussage Fall besser lesbar.

0

Die errors package hat die folgenden Operationen in Control.Error.Util (und reexportiert von Control.Error):

-- You can turn `Maybe` into `Either` by supplying a constant to use 
-- for the `Left` case. 
note :: a -> Maybe b -> Either a b 

-- Ditto for `MaybeT` and `ExceptT` 
noteT :: Monad m => a -> MaybeT m b -> ExceptT a m b 

-- And there are useful shortcuts for other combinations 
failWith :: Applicative m => e -> Maybe a -> ExceptT e m a 

failWith insbesondere sieht aus wie es hier ganz gut passen würde, so etwas wie dieser Ausdruck würde den Trick.

failWith "Err" (Map.lookup (VarName name) envFun) 

Beachten Sie, dass die ErrorT Transformator, die Sie in Ihrem Beispiel verwenden hat sich für ExceptT veraltet (wie die oben genannten Signaturen verwenden), so dass Sie Ihren Code ändern, müsste demnach die errors zu verwenden Paket. Auf der anderen Seite sind diese Funktionen einfach genug, dass Sie Ihre eigenen backen können, wenn Sie es bevorzugen.

Verwandte Themen