Skip to content
0:00 / 0:00

#monadtransformers#haskell#monad-control

Monad Transformer State - Michael Snoyman

Lambda World

10K subscribers • 16 videos on Hallway

YouTube
  • Recommended by 1 person: 1 in engineering communities.
  • Presented by Michael Snoyman

Advanced. Deep dive for people who know the field.

14K views8 years ago1 recommendation

Programming languagesSoftware designHaskellFunctional programmingConcurrency and parallelism

Michael Snoyman explains the surprising behaviors of implicit state in monad transformers and how to structure Haskell applications safely.

Everything you didn’t want to know about monad transformer state was a presentation given as part of Lambda World 2017 by Michael Snoyman. Follow: -twitter.com/47deg -twitter.com/lambda_world -twitter.com/snoyberg Visit: -47deg.com/events for more details ___ Monad transformers are often used in Haskell applications to model state, capture results, and deal with explicit exceptions. In order to make these monad transformer stacks work with concurrency primitives, runtime exceptions, and more, we'll often use libraries like lifted-base, lifted-async, monad-control, and exceptions. But contrary to the expectations of many, surprising things can happen with the implicit state of our transformers. This talk will explain the problem, demonstrate where surprising behavior pops up, and recommend ways to structure your libraries and applications to sidestep the issue entirely.

Why it's here

1 person recommends this

What people say. Recommended for its deep dive into the complexities and pitfalls of monad transformer state in concurrent Haskell applications.

Moments people linked to

u/snoyjerkin r/haskell • Recommends

Everything you didn’t want to know about monad transformer state

u/Faucelmein r/haskell • Mentions

On “Why exactly I want Boring Haskell to happen”

> Reader pattern, unliftio (but not rio), etc. But to me this camp is taking it way too far - almost nobody came to Haskell with the desire to write "boring Haskell", many people I know chose Haskell because it allows to express type invariants in a wider range of scenarios than other languages. My opinion about unliftio is that it *doesn't* represent an incurious retreat into boringness. It was the product of thinking about the monad-control way of doing things and realizing that it combined a lot of complexity with arbitrary and unprincipled semantics, making it very much not worth it. (The wonkiness of monad-control has been noticed elsewhere.) At the very least, unliftio has the mer…

u/snoybergin r/haskell • Mentions

On “RIO: A Prelude Replacement”

The most complete explanation was probably in the talk I gave at Lambda World, "Everything you didn't want to know about monad transformer state" (Slides Video). The short version is: * If you're in pure code: use State, Writer, and everything else as much as you want * If you're in a small subsection of your code that needs some extra effect, use a transformer * When you're modeling your application itself, and you're coming up with a monad stack that your whole app will live in: `StateT` and `WriterT` don't really behave in any pure way, in that you don't get purity benefits. Plus, you get lots of costs, in improper concurrency management and losing state in exception handling. So if yo…

u/Faucelmein r/haskell • Mentions

On “Demystifying `MonadBaseControl`”

About the problems with forking state, the post says: > As with sideEffect, we can’t recover the output state, but in this case, there’s a fundamental reason that goes deeper than the types: we’ve forked off a concurrent computation! A bigger problem is when *rejoining* two concurrent computations, like with `concurrently`. lifted-async unceremoniously drops the state generated by one of the computations, as explained in this talk by Michael Snoyman. For me, this kind of arbitrary behaviour not guided by an underlying theory or reasoning principle makes the extra complexity of monad-control harder to countenance. Now, there could be more specialized, less general versions of monad-con…
11View on Reddit

u/Faucelmein r/haskell • Mentions

On “Monthly Hask Anything (April 2020)”

> why were they all put into their own separate Monad type? There is a current of opinion which agrees with that philosophy of avoiding complex monad stacks "in the large"—though they might still be considered ok for localized parts of the application. Check out packages like unliftio and rio which limit themselves to a Reader transformer on top of IO. This talk by Michael Snoyman is also relevant.

u/shiraeeshiin r/haskell • Mentions

On “Error handling in the RIO and UnliftIO world”

Here is what the "Safe exception handling" article says in "Exceptions best practices" section (the last section): > The Haskell runtime system allows any IO action to throw runtime exceptions. Many common library functions throw runtime exceptions. There is no indication at the type level if something throws an exception. You should assume that, unless explicitly documented otherwise, all actions may throw an exception. > It's not worth trying to fight the system and make all possible error cases explicit. Other languages, like Rust, go this route, and it works well in practice. But that's because it's an ethos throughout the entire ecosystem. In Haskell, you're fighting against the curre…

u/dfordivamin r/haskell • Mentions

On “though about multi threading in haskell”

I see problem with this approach. You want to share some state with multiple concurrent threads right? You might have to use TVar for that.. There is a nice talk about this here link to this video

u/Faucelmein r/haskell • Mentions

On “Monthly Hask Anything (December 2018)”

I'm not a fan of monad-control. This post and this video touch on some of the problems with the library.
2View on Reddit

u/Faucelmein r/haskell • Mentions

On “Help needed: Scraping web pages concurrently and saving the results to a big JSON file, in constant memory”

My opinion is that "blundering ahead" is a prerequisite for understanding, because we learn better with examples which are relevant for us. (Of course, we should take a step back once in a while and try to understand what we have done.) If you are working in `IO`, just remember that `IO` has a `MonadUnliftIO` instance, so you can use any function from `unliftio` with the monad specialized to `IO` and it will work. The nice thing about `unliftio` is that if you move to a `ReaderT` transformer over `IO` (to carry around configuration or inject capabilities for example) all the `unliftio` functions will keep working with the new monad stack. This talk by Michael Snoyman is a good introduct…
2View on Reddit

u/kuleshevichin r/haskell • Mentions

On “Forcing exceptions to be listed in the type signature”

At my work we believe this is to be an anti-pattern, see the part in Exceptions best practices( https://www.fpcomplete.com/haskell/tutorial/exceptions/#exceptions-best-practices) and I totally agree with it. It is good to use `Either` to handle failures, same with `ExceptT`, it does come in handy sometimes, but by no means they are a replacement for runtime exceptions. Check out this Michael Snoyman's talk and I hope it can convince you that the pattern you describe can't work reliably.