2017-01-29 4 views
0

Er Jungs, ich habe ein Problem. Ich habe zwei Funktionen in meinem Haskell-Programm.Haskell: Arbeiten mit Fehlern/Ausnahmen in Haskell

type Env = String -> Int 

emptyEnv :: Env 
emptyEnv _ = error "Failed" 

insertEnv :: String -> Loc -> Env -> Env 
insertEnv s loc env = case env s of 
         (error "Failed") -> (\inp -> (if inp==s then loc else env s)) 
         _ -> env 

Also mein leerEnv sollte immer eine Fehlermeldung geben. Mit der anderen Funktion insertEnv können Sie Elemente in Env einfügen. Sie müssen daher überprüfen, ob Env leer ist und auf dem Bildschirm wird ein Fehler angezeigt. Nun meine Frage: Der obige Code funktioniert nicht, weil der Fehler "Failed" kein Fall von env s in der Funktion insertEnv ist. Hast du eine Idee, wie ich den Fehler richtig behandle, damit du Elemente in env einfügen kannst?

Antwort

2

Mit der anderen Funktion insertEnv können Sie Elemente in Env einfügen. Sie müssen also prüfen, ob Env leer ist.

Warum müssen Sie prüfen, ob eine Umgebung leer ist, bevor Sie etwas einfügen? Eine Umgebung, die die Variable x enthält, ist nur eine Funktion, die bei Angabe des Namens x den Wert zurückgibt, an den x gebunden war.

insertEnv s loc env = \v -> if v == s then loc else env v 
3

Wir behandeln in der Regel Funktionen in Haskell, indem sie andernfalls eine Maybe Art Rückkehr:

type Loc = Int 
type Env = String -> Maybe Loc -- Here 

emptyEnv :: Env 
emptyEnv _ = Nothing 

Und für insertEnv würden wir schreiben:

insertEnv :: String -> Loc -> Env -> Env 
insertEnv s loc env inp = 
    case env inp of 
    Nothing -> 
     if s == inp 
     then Just loc 
     else Nothing 
    Just loc' -> Just loc' 

, die durch nicht machen Ihre beabsichtigte Bedeutung folgt Ein Insert aktualisiert die Env. Eine weitere Möglichkeit für insertEnv ist auf „aktualisieren“, um die Umwelt:

insertEnv' :: String -> Loc -> Env -> Env 
insertEnv' key loc env inKey 
    | key == inKey = Just loc 
    | otherwise = env inKey 

Wenn Sie interessiert sind, können beide Versionen mit den First und Last Wrapper von Data.Monoid implementiert werden.

import Data.Monoid 

type Env' = String -> First Loc -- Choose First or Last here 

emptyEnv' :: Env' 
emptyEnv' _ = mempty 

insertEnv' :: String -> Loc -> Env' -> Env' 
insertEnv' s loc env inp = 
    env inp <> 
    if s == inp 
    then pure loc 
    else mempty 

Mit etwas Umwelt

env1 = insertEnv' "1" 2 (insertEnv' "1" 1 emptyEnv') 

Wenn Sie First mit der obigen Implementierung holen erhalten Sie

GHCI> env1 "1" 
First {getFirst = Just 1} 

oder mit Last

GHCI> env1 "1" 
Last {getLast = Just 2} 
+0

Dank Adamse. Schnell außerhalb des Themas. Jetzt habe ich es einfach mit 'emptyEnv = \ _-> (- 1)' und 'insert s loc env = \ inp -> (wenn inp == s dann loc else env s)' aber jetzt, wenn ich das 'env = füge "x" ein 42 (füge "y" ein 17 emptyEnv) 'und dann' env "y" 'es gibt mir -1 so das vale eines leeren Env. Was ist da los? Es hat vor 5 Minuten funktioniert !? –

+0

Sie möchten '... sonst env inp'. – adamse