2016-04-10 17 views
4

Betrachten wir:Monade-Transformatoren. Erster Schritt

type Name = String    -- variable names 

data Exp = Lit Integer   -- expressions 
      | Var Name 
      | Plus Exp Exp 
      | Abs Name Exp 
      | App Exp Exp 
      deriving (Show) 

data Value = IntVal Integer  -- values 
      | FunVal Env Name Exp 
      deriving (Show) 

type Env = Map.Map Name Value -- mapping from names to values 

eval0 :: Env -> Exp -> Value 
eval0 env (Var n) = fromJust (Map.lookup n env) 

Und oben ist 0 Version. Jetzt

, lassen Sie uns betrachten monadischen, 1 Version:

type Eval1 a = Identity a 
eval1 :: Env -> Exp -> Eval1 Value 
eval1 env (Var n) = Map.lookup n env 

Und jetzt, sagte der Autor:

Das nächste ist, dass der Var Fall kein fromJust Anruf braucht mehr: Die Grund ist, dass Map.lookup so definiert ist, dass es in jeder Monade funktioniert, indem man einfach die Fail-Funktion der Monade aufruft - das passt gut zu unserer monadischen Formulierung hier. (Die Fail-Funktion des Vielleicht gibt nichts zurück Monade, während die Funktion fehl in der Identity Monade eine Ausnahme auslöst, die zu unterschiedlichen Fehlermeldungen führen.)

Der Inhalt stammt aus: http://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf und es ist nicht klar für mich. Bitte erklären Sie, warum die Einführung von Monad Eval1 es uns erlaubt, sich nicht um zu kümmern.

EDIT:

Jetzt habe ich versucht, es zu kompilieren und ich bekam Fehler und dieser Fehler steht im Einklang mit meiner Intuition und meine Zweifel. Der Compiler sagt:

Couldn't match type `Maybe Value' with `Identity Value' 
Expected type: Eval1 Value 
    Actual type: Maybe Value 
In the return type of a call of `Map.lookup' 
In the expression: Map.lookup n env 
In an equation for `eval1': eval1 env (Var n) = Map.lookup n env 

Also, wer Recht hat, Autor oder Compiler und wie es zu reparieren?

+0

Ich glaube, der Autor hatte vor einiger Zeit Recht, wo "Lookup" verwendet wurde, 'm a' für jede Monade' m' zurückzugeben. Jetzt gibt 'lookup' nur' Maybe a' zurück. – chi

+0

Als ich diese Zeitung vor ein paar Wochen gelesen habe, hatte ich dieselbe Frage. Ich habe eine aktualisierte Version des Papiers (oder zumindest des Codes) gefunden, die das behoben hat; Ich werde sehen, ob ich den Link ausgraben kann. – chepner

Antwort

6

Zu dem Zeitpunkt, Entwurf geschrieben wurde, tat Data.Map.lookup anscheinend Arbeit mit jeder Monade. Dies ist nicht mehr richtig, aber der Autor bietet eine des Tutorials.

Speziell müssen Sie den resultierenden Maybe String Wert untersuchen und fail explizit aufrufen.

-- Copied from the link above 
eval1 env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env 
2

Der Grund dafür ist, dass Map.lookup definiert wird durch einfaches Aufrufen der Monade innerhalb einer Monade arbeiten scheitern Funktion

Es ist nicht wahr. Im Text unterscheidet sich die Definition von Map.lookup von der echten Definition in containers Paket. Der Autor Map.lookup einen monadischen Wert verallgemeinerte, nicht nur Maybe:

lookup' :: (Ord k, Monad m) => k -> Map k a -> m a 
lookup' k m = case Map.lookup k m of 
    Nothing -> fail "some_error_message" 
    Just v -> return v