
Hi all,
I have a family of parsers that return either (Success t) or (Fail), using
В сообщении от Четверг 07 января 2010 21:35:10 rodrigo.bonifacio написал: the following data type:
data ParserResult a = Success a | Fail String deriving (Read, Show, Eq, Ord)
isSuccess (Success _) = True isSuccess (Fail _) = False ...
I want to add the results of different parsers to a list. Such as:
m1 = parseFirstModel file1 -- it returns a ParserResult of t1 m2 = parseSecondModel file2 -- it returns a ParserResult of t2
ps = [m1, m2]
In such a way that I could write something like:
if and (map isSuccess ps) then process m1 m2 else ...
Actually, in the real program I have to check more than two input models. However, since Lists do only hold elements of a same type, I couldn't proceed in this way. Which improvements to the ParserResult data type should I wrote in order to proceed as I want to.
In short there is no easy way to this lists. But you can make ParserResult instance of Monad and/or Applicative. It's is error monad in fact. You can check Control.Monad.Error to see Monad instance for (Either String) With this you can write you program in applicative notation Here computation will stop after first error.
m1 = parseFirstModel file1 -- it returns a ParserResult of t1 m2 = parseSecondModel file2 -- it returns a ParserResult of t2
case process <$> m1 <*> m2 of (Success x) -> ... (Fail x) -> ...
Or use do notation with similar results
res = do m1 <- parseFirstModel file1 m2 <- parseSecondModel file2 return $ process m1 m2
foo = case res of (Success x) -> ... (Fail err) -> ...
P.S. I didn't run code but I think it should work if required instances are defined