<div dir="auto">Looks like `MonadError String` to me.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 20 Nov 2020, 1:08 pm Dannyu NDos, <<a href="mailto:ndospark320@gmail.com">ndospark320@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Firstly, I propose a new class. This class is like MonadFail, but with<br>
"error bind" operator:<br>
<br>
class Monad m => FailMsg m where<br>
failMsg :: String -> m a<br>
(>?=) :: m a -> (String -> m a) -> m a<br>
<br>
Laws are:<br>
<br>
* For every (x :: m a), if (x ≡ fail msg) for some (msg :: String),<br>
msg shall be unique.<br>
* For (x ≡ fail msg), (x >?= f ≡ f msg). If such msg doesn't exist,<br>
(x >?= _ ≡ x).<br>
<br>
Basic instances are:<br>
<br>
instance e ~ String => FailMsg (Either e) where<br>
failMsg = Left<br>
Left msg >?= f = f msg<br>
x >?= _ = x<br>
<br>
instance FailMsg IO where<br>
failMsg = throwIO . userError<br>
action >?= f = catch action (f . ioeGetErrorString)<br>
<br>
Now let's focus on ReadP. Let P carry a failure message:<br>
<br>
data P a<br>
= Get (Char -> P a)<br>
| Look (String -> P a)<br>
| Fail String<br>
| Result a (P a)<br>
| Final (NonEmpty (a,String))<br>
<br>
Then we have:<br>
<br>
instance FailMsg P where<br>
fail = Fail<br>
Fail msg >?= f = f msg<br>
p >?= _ = p<br>
<br>
instance FailMsg ReadP where<br>
fail msg = R (\_ -> fail msg)<br>
R m >?= f = R (\k -> case m k of<br>
Fail msg -> let<br>
R n = f msg<br>
in n k<br>
p -> p<br>
)<br>
<br>
This is incredibly useful. This can be used when there are multiple<br>
types of parse error.<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank" rel="noreferrer">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>