Skip to content

add MonadThrow and MonadCatch instances for Stream - #121

Open
mauke wants to merge 3 commits into
haskell-streaming:masterfrom
mauke:monad-throw-catch
Open

add MonadThrow and MonadCatch instances for Stream#121
mauke wants to merge 3 commits into
haskell-streaming:masterfrom
mauke:monad-throw-catch

Conversation

@mauke

Copy link
Copy Markdown

No description provided.

These are equivalent to the code in the existing MonadError instance.
@mauke
maukeforce-pushed the monad-throw-catch branch from b9a5793 to 357749bCompareJuly 4, 2023 18:33
@treeowl

Copy link
Copy Markdown
Contributor

Please leave a comment proving the MonadCatch law. Please also document (somewhere in the Haddocks) how these instances behave, preferably with a few examples, including both "good" examples of desirable behavior and "bad" examples of behavior that might not be what the user expected/desired.

@mauke

mauke commented Jul 5, 2023

Copy link
Copy Markdown
Author

Is the following correct/complete?


I can prove the MonadThrow and MonadCatch laws under the assumption that a >> b = a >>= \_ -> b (which I don't see formally stated anywhere, but I'm going to assume it anyway).

Lemma 1:

throwM e >>= f = throwM e

Proof:

throwM e >>= f =-- MonadThrow law (in reverse) for some arbitrary action 'w'-- (in particular, you can always choose w = throwM e)
(throwM e >> w) >>= f =-- my assumption
(throwM e >>=\_ -> w) >>= f =-- Monad associativity
throwM e >>= (\x -> (\_ -> w) x >>= f) =-- beta reduction
throwM e >>= (\_ -> w >>= f) =-- my assumption, again
throwM e >> (w >>= f)
-- MonadThrow law
throwM e

Lemma 2:

fmap f (throwM e) = throwM e

Proof:

fmap f (throwM e) =-- behavior of fmap for monads
throwM e >>=return. f
-- lemma 1
throwM e

Theorem 1 (MonadThrow law for Stream f m):

throwM e >> f = throwM e

Proof:

throwM e >> f =-- definition of throwM, (>>) for Stream
lift (throwM e) *> f =-- definition of lift for StreamEffect (fmapReturn (throwM e)) *> f =-- lemma 2 for mEffect (throwM e) *> f =-- definition of (*>) for StreamEffect (fmap loop (throwM e)) =-- this 'loop' is a local function in (*>) and hides a reference to 'f'-- lemma 2 for mEffect (throwM e) =-- lemma 2 for mEffect (fmapReturn (throwM e)) =-- definition of lift for Stream
lift (throwM e) =-- definition of throwM for Stream
throwM e

Theorem 2 (MonadCatch law for Stream f m):

catch (throwM e) f = f e

Proof:

catch (throwM e) f =-- definition of throwM for Stream
catch (lift (throwM e)) f =-- definition of lift for Stream
catch (Effect (fmapReturn (throwM e))) f =-- lemma 2 for m
catch (Effect (throwM e)) f =-- definition of catch for StreamEffect (fmap loop (throwM e) `catch` (return. f)) =-- lemma 2 for mEffect (throwM e `catch` (return. f)) =-- MonadCatch law for mEffect (return (f e))
-- definition of effect
effect (return (f e))
-- specification/law of effect
(join . lift) (return (f e))
-- associativity of (.)
join ((lift .return) (f e))
-- MonadTrans law
join (return (f e))
-- definition of joinreturn (f e) >>=id-- Monad lawid (f e)
-- definition of id
f e

@mauke

mauke commented Jul 10, 2023

Copy link
Copy Markdown
Author

As for examples of desirable behavior, do you mean something like this?

S.print (doS.yield "start"do { xs <- liftIO $fmaplines (readFile"some-imaginary-file");
S.each xs }
S.yield "finish"
)
{-"start"*** Exception: some-imaginary-file: openFile: does not exist (No such file or directory)-}
S.print (doS.yield "start"do { xs <- liftIO $fmaplines (readFile"some-imaginary-file");
S.each xs }
`catchIOError` (\e ->do
liftIO $ hPutStrLn stderr $"caught an error: "++show e
S.yield "something else"
)
S.yield "finish"
)
{-"start"caught an error: some-imaginary-file: openFile: does not exist (No such file or directory)"something else""finish"-}

What would "bad" behavior look like?

@mauke

Copy link
Copy Markdown
Author

@treeowl Ping?

@treeowl

Copy link
Copy Markdown
Contributor

Been sick for a week. Please ping again later.

@mauke

Copy link
Copy Markdown
Author

Get well soon!

@mauke

Copy link
Copy Markdown
Author

Ping?

@Topsii

Copy link
Copy Markdown

@treeowl ping

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@mauke@treeowl@Topsii