2016-04-09 19 views
2

Ich möchte eine Zeichenfolge nehmen und in eine Liste von Direction verwandeln. Beispielsweise sollte "UDDUD"[U,D,D,U,D] zurückgeben, während jede Zeichenfolge, die keine U oder enthält, Nothing zurückgibt (z. B. "UDYD" gibt Nothing zurück).Haskell - Maybe und Rekursion

data Direction = U | D 
    deriving (Show, Eq) 
-- where U is Up and D is Down 

findDirection :: [Char] -> Maybe [Direction] 
findDirection [] = Nothing 
findDirection ['U'] = Just [U] 
findDirection ['D'] = Just [D] 
findDirection (x:xs) 
    | x == 'U' = Just (U : findDirection xs) 
    | x == 'D' = Just (D : findDirection xs) 
    | otherwise = Nothing 

ich die folgende Fehlermeldung erhalten:

Couldn't match expected type ‘[Direction]’ 
       with actual type ‘Maybe [Direction]’ 
    In the second argument of ‘(:)’, namely ‘findDirection xs’ 
    In the first argument of ‘Just’, namely 
     ‘(U : findDirection xs)’ 

Test_findDirection.hs:8:32: 
    Couldn't match expected type ‘[Direction]’ 
       with actual type ‘Maybe [Direction]’ 
    In the second argument of ‘(:)’, namely ‘findDirection xs’ 
    In the first argument of ‘Just’, namely 
     ‘(D : findDirection xs)’ 

Wie ich es verstehe, Just (D : findDirection xs) und Just (U : findDirection xs) sind vom Typ [Direction]? Warum ist das der Fall? Was mache ich hier falsch?

+1

'U: findirection xs' (und' D: findDirection xs') ist schlecht typisiert: Man kann eine 'Direction' nicht zu einer' Maybe [Direction] 'machen. Außerdem schreiben Sie: * [...] jeder String, der kein 'U' oder' D' enthält, gibt 'Nothing' zurück (zB' 'UDYD'' gibt 'Nothing' zurück). * Widersprichst du dir nicht selbst, hier ? – Jubobs

Antwort

5

Just (D : findDirection xs) and Just (U : findDirection xs) are of type [Direction]? Why is this the case? What am I doing wrong, here?

Nein, Just (D : findDirection xs) ist eigentlich schlecht getippt. Lassen Sie uns diese Fehlermeldung sezieren:

Couldn't match expected type ‘[Direction]’ 
       with actual type ‘Maybe [Direction]’ 

Wir Maybe [Direction] an einem Punkt mit sind, wo wir eigentlich [Direction] verwenden sollten.

In the second argument of ‘(:)’, namely ‘findDirection xs’ 

Aha. Wir verwenden (:) :: a -> [a] -> [a] falsch. Immerhin wird findDirection eine Maybe [Direction], nicht eine [Direction] zurückgeben. Wir brauchen so etwas wie dieses:

consOnMaybe :: a -> Maybe [a] -> Maybe [a] 
consOnMaybe _ Nothing = Nothing 
consOnMaybe x (Just xs) = Just (x : xs) 

Jetzt können Sie Ihre Funktion als

geschrieben werden
findDirection (x:xs) 
    | x == 'U' = consOnMaybe U (findDirection xs) 
    | x == 'D' = consOnMaybe D (findDirection xs) 
    | otherwise = Nothing 

Alternativ könnten wir consOnMaybe x = fmap (x:) verwendet haben. Als zusätzlichen Bonus, hier ist eine Variante, die vordefinierten Funktionen und keine explizite Rekursion (Übung: verstehen, wie es funktioniert) verwendet

findDirection :: [Char] -> Maybe [Direction] 
findDirection [] = Nothing 
findDirection xs = traverse toDirection xs 

toDirection :: Char -> Maybe Direction 
toDirection 'U' = Just U 
toDirection 'D' = Just D 
toDirection _ = Nothing 
0
data Direction = U | D 
    deriving (Show, Eq) 

    findDirection :: String -> Maybe [Direction] 
    findDirection [] = Nothing 
    findDirection dirs = sequence $ findDirection' dirs 
    where 
     findDirection' :: String -> [Maybe Direction] 
     findDirection' (x:xs) = 
     let x' = toDirection x in 
      x' : case x' of 
       Just _ -> findDirection' xs 
       _ -> [] 
     findDirection' _ = [] 

     toDirection :: Char -> Maybe Direction 
     toDirection 'U' = Just U 
     toDirection 'D' = Just D 
     toDirection _ = Nothing 

------------------------ OR ------------------------ 

findDirection :: String -> Maybe [Direction] 
    findDirection [] = Nothing 
    findDirection dirs = traverse toDirection dirs 
    where 
     toDirection :: Char -> Maybe Direction 
     toDirection 'U' = Just U 
     toDirection 'D' = Just D 
     toDirection _ = Nothing 

> findDirection "UDDUD" 
< Just [U,D,D,U,D] 

> findDirection "UDYD" 
< Nothing