# Stepping into arbitrary monads from a REPL

**URL:** <https://discourse.haskell.org/t/stepping-into-arbitrary-monads-from-a-repl/14917>\
**Category:** Show and Tell\
**Created:** [October 31, 2026, 12:17pm UTC](https://discourse.haskell.org/t/stepping-into-arbitrary-monads-from-a-repl/14917 "2026-10-31T12:17:28Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![bglgwyng](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/bglgwyng/32/4377_2.png) [@bglgwyng](https://discourse.haskell.org/u/bglgwyng)\
**Post date:** [October 31, 2026, 12:17pm UTC](https://discourse.haskell.org/t/stepping-into-arbitrary-monads-from-a-repl/14917/1 "2026-10-31T12:17:28Z")

</div>

GHCi always runs statements in `IO`. I wanted to step into `StateT`, `ReaderT` or an app monad, work there for a while, and step back out. So I made a small proof of concept.

[https://raw.githubusercontent.com/bglgwyng/haskell-playground/refs/heads/repl/assets/demo.mp4](https://raw.githubusercontent.com/bglgwyng/haskell-playground/refs/heads/repl/assets/demo.mp4)

`:e runner` takes any `runner :: n () -> m ()`, infers `n` with a typed hole, and opens a nested REPL inside `n`. `:q` steps back out.

Code: [haskell-playground/exe/playground.hs at repl · bglgwyng/haskell-playground · GitHub](https://github.com/bglgwyng/haskell-playground/blob/repl/exe/playground.hs)

Related: [GHC #9966](https://gitlab.haskell.org/ghc/ghc/-/issues/9966) proposes the same idea for GHCi.
