简体   繁体   中英

Haskell String to Maybe List

readSquareTransition :: String -> Maybe [SquareTurn]
readSquareTransition [] = Just []
readSquareTransition (x:xs) = case x of
      'L' -> Just (L : readSquareTransition xs)
      'R' -> Just (R : readSquareTransition xs)
       _      -> Nothing

I want to get Just [L,L,R,R]. But looks like i failed :( Here is the error message!

src/StudentSources/LangtonsAnt.hs:231:24:
Couldn't match expected type ‘[SquareTurn]’
            with actual type ‘Maybe [SquareTurn]’
In the second argument of ‘(:)’, namely ‘readSquareTransition xs’
In the first argument of ‘Just’, namely
  ‘(L : readSquareTransition xs)’

src/StudentSources/LangtonsAnt.hs:232:24:
Couldn't match expected type ‘[SquareTurn]’
            with actual type ‘Maybe [SquareTurn]’
In the second argument of ‘(:)’, namely ‘readSquareTransition xs’
In the first argument of ‘Just’, namely
  ‘(R : readSquareTransition xs)’

Change this

'L' -> Just (L : readSquareTransition xs)
'R' -> Just (R : readSquareTransition xs)

to this

'L' -> fmap (L :) $ readSquareTransition xs
'R' -> fmap (R :) $ readSquareTransition xs

The problem is that readSquareTransition returns a Maybe [SquareTurn] , so you can't apply (:) to it ( (:) requires a List). fmap however lets you apply into the Just (while preserving a Nothing ).

A modular way of doing this would be to define readSquareTurn first which defines how to turn a Char into a single SquareTurn (with the possibility of failure):

readSquareTurn :: Char -> Maybe SquareTurn
readSquareTurn x = case x of
  'L' -> Just L
  'R' -> Just R
  _   -> Nothing

and then use mapM :: (a -> Maybe b) -> [a] -> Maybe [b] to process the whole String like so:

readSquareTransition :: String -> Maybe [SquareTurn]
readSquareTransition = mapM readSquareTurn

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM