Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map (Either String (a -> b)) to (Either String [(a -> b)])

I try to find a solution on an exercise of my own, with the following requirements :

  • We need to move an object against a given sequence.
  • A sequence is composed of actions.

Here are the possible actions : F, L, R

  • F : move Forward
  • L : rotate 90° to the left
  • R : rotate 90° to the right

A sequence is then represented by a string, like this :

"FFLRLFF"

I want to parse the above sequence (and handle errors) and then bind each action to a function, like this :

parseAction :: Char -> Either String (a -> a)
parseAction 'F' = Right moveForward
parseAction 'L' = Right turnLeft
parseAction 'R' = Right turnRight
parseAction s   = Left ("Unkown action : " ++ [s])

-- Implementation omitted
moveForward :: a -> a
turnLeft :: a -> a
turnRight :: a -> a

Now what I want is something with the following signature :

parseSequence :: String -> Either String [(a -> a)]

I want to parse a full sequence by using many times parseAction function, and fails when that one returns Left. I'm stuck on how can I implement this function.

Do you have any ideas ?

like image 379
Maxime Avatar asked Sep 11 '15 19:09

Maxime


1 Answers

This looks like

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

where

a ~ Char
b ~ (a -> a)
m ~ (Either String)

So an implementation is simply:

parseSequence :: String -> Either String [a -> a]
parseSequence = mapM parseAction

As an aside, note that your parseAction doesn't really want to be using type (a -> a), which must work for any type a, chosen by the person calling the function. You instead want it to use type (Location -> Location), where Location is whatever type you're using to represent the location of the object you're moving.

Equivalently to mapM, you can (as suggested by duplode) instead use traverse, which is slightly more general. In recent versions of GHC traverse is in Prelude; in older versions you may have to import it from Data.Traversable to use it.

like image 77
amalloy Avatar answered Sep 22 '22 00:09

amalloy