On Wed, Nov 4, 2015 at 9:28 AM, Jules Bean <jules@jellybean.co.uk> wrote:

On 4 Nov 2015, at 13:04, Michael Snoyman <michael@snoyman.com> wrote:

This got me curious, so I just added a `sourceToList` function to master:


Having spent a day thinking this over…

Nothing with the type `Source m a -> m [a]` can work for my second example - the one where I use runExceptionT to discharge the MonadThrow constraint. This is because once you use runExceptionT you have pushed yourself into the situation where in case of error there is no ‘return value’. 

It’s not that I care about that per se - if there is an error then the return value is no use to me - but unfortunately that has knock-on implications on laziness.

The Writer monad solution pushes out the return value incrementally by a ‘side-channel’ rather than using the return value and it’s that property which lets it work even in the presence of runExceptionT.

Another approach which would work though is to provide a newtyped Identity monad which handles MonadThrow by _|_, which would allow you to regain laziness (?)

Jules



I don't think that the Writer example above is demonstrating what you're saying, since you're using imprecise exceptions (`error`) instead of MonadThrow. You could do the same thing with sourceToList and get that result.

You're also correct that some kind of a Identity monad with a MonadThrow instance based on `throw` would allow this to work.

Michael