I was playing around with implementing a simple parser for some stuff in Haskell and got to the point where most o the basic functionality works (more or less) and I wanted to add some extra stuff for displaying the errors.
Long story short, I realized that for implementing the Monoid type class I first needed to implement the Semigroup, and this is the best way to implement it that I could come up with. I like it, but it feels kind of ugly having to reference mempty
from inside the Semigroup instance definition. Is there a prettier way to implement those type classes?
Appreciate all comments in advance!
data ParserError = ExpectedChar Char Char -- expected CHAR(1) but was CHAR(2)
| ExpectedEOL Char -- expected EOL but was CHAR(1)
| UnexpectedEOL Char -- expected CHAR(1) but was EOL
-- Special errors:
| EmptyError -- for the applicative to work
| AggregationError [ParserError] -- several errors occured (ex. during alternative)
instance Semigroup ParserError where
mempty <> e = e
e <> mempty = e
(AggregationError e1) <> (AggregationError e2) = AggregationError (e1 ++ e2)
(AggregationError e1) <> e2 = AggregationError (e1 ++ [e2])
e1 <> (AggregationError e2) = AggregationError (e1 : e2)
e1 <> e2 = AggregationError [e1, e2]
instance Monoid ParserError where
mempty = EmptyError