HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleturtle-1.6.2Haskell2010

Turtle.Shell

You can think of Shell as [] + IO + Managed. In fact, you can embed all three of them within a Shell:

select ::        [a] -> Shell a
liftIO ::      IO a  -> Shell a
using  :: Managed a  -> Shell a

Those three embeddings obey these laws:

do { x <- select m; select (f x) } = select (do { x <- m; f x })
do { x <- liftIO m; liftIO (f x) } = liftIO (do { x <- m; f x })
do { x <- with   m; using  (f x) } = using  (do { x <- m; f x })

select (return x) = return x
liftIO (return x) = return x
using  (return x) = return x

... and select obeys these additional laws:

select xs <|> select ys = select (xs <|> ys)
select empty = empty

You typically won't build Shells using the Shell constructor. Instead, use these functions to generate primitive Shells:

Then use these classes to combine those primitive Shells into larger Shells:

If you still insist on building your own Shell from scratch, then the Shell you build must satisfy this law:

-- For every shell `s`:
_foldShell s (FoldShell step begin done) = do
    x' <- _foldShell s (FoldShell step begin return)
    done x'

... which is a fancy way of saying that your Shell must call 'begin' exactly once when it begins and call 'done' exactly once when it ends.

  • 2 types
  • 10 values
  • Packageturtle-1.6.2
  • Exports14
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceShell.hs

Shell

10 declarations
newtypenewtype Shell a
#

A (Shell a) is a protected stream of a's with side effects

Constructors

Instances14Monad, Functor, MonadFail, Applicative, Alternative, MonadPlus, …
datadata FoldShell a b
#

This is similar to FoldM IO except that the begin field is pure

This small difference is necessary to implement a well-behaved MonadCatch instance for Shell

Constructors

value_foldIO :: Shell a -> FoldM IO a r -> IO r
#

Provided for backwards compatibility with versions of turtle-1.4.* and older

value_Shell :: (forall r. FoldM IO a r -> IO r) -> Shell a
#

Provided for ease of migration from versions of turtle-1.4.* and older

valuereduce :: MonadIO io => Fold a b -> Shell a -> io b
#

Flipped version of fold. Useful for reducing a stream of data

Example

Sum a Shell of numbers:

Example1 expression
select [1, 2, 3] & reduce Fold.sum6
valuesh :: MonadIO io => Shell a -> io ()
#

Run a Shell to completion, discarding any unused values

Embeddings

4 declarations
methodliftIO :: IO a -> m a
#

Lift a computation from the IO monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. IO is the base monad for the stack).

Example
import Control.Monad.Trans.State -- from the "transformers" library

printState :: Show s => StateT s IO ()
printState = do
  state <- get
  liftIO $ print state

Had we omitted liftIO, we would have ended up with this error:

• Couldn't match type ‘IO’ with ‘StateT s IO’
 Expected type: StateT s IO ()
   Actual type: IO ()

The important part here is the mismatch between StateT s IO () and IO ().

Luckily, we know of a function that takes an IO a and returns an (m a): liftIO, enabling us to run the program and see the expected results:

> evalStateT printState "hello"
"hello"

> evalStateT printState 3
3