bluefin-internal-0.0.15.0: The Bluefin effect system, internals
Safe HaskellSafe-Inferred
LanguageHaskell2010

Bluefin.Internal

Synopsis

Documentation

data Effects Source #

Constructors

Union Effects Effects 

Instances

Instances details
Handle (ConstEffect r :: Effects -> Type) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => ConstEffect r e -> ConstEffect r es Source #

type (:&) = Union infixr 9 Source #

type (:&) :: Effects -> Effects -> Effects

Union of effects

newtype Eff (es :: Effects) a Source #

Constructors

UnsafeMkEff 

Fields

Instances

Instances details
Applicative (Eff es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

pure :: a -> Eff es a #

(<*>) :: Eff es (a -> b) -> Eff es a -> Eff es b #

liftA2 :: (a -> b -> c) -> Eff es a -> Eff es b -> Eff es c #

(*>) :: Eff es a -> Eff es b -> Eff es b #

(<*) :: Eff es a -> Eff es b -> Eff es a #

Functor (Eff es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

fmap :: (a -> b) -> Eff es a -> Eff es b #

(<$) :: a -> Eff es b -> Eff es a #

Monad (Eff es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

(>>=) :: Eff es a -> (a -> Eff es b) -> Eff es b #

(>>) :: Eff es a -> Eff es b -> Eff es b #

return :: a -> Eff es a #

newtype EffReader r es a Source #

Because doing IO operations inside Eff requires a value-level argument we can't give IO-related instances to Eff directly. Instead we wrap it in EffReader.

Constructors

MkEffReader 

Fields

Instances

Instances details
e :> es => MonadBaseControl IO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Associated Types

type StM (EffReader (IOE e) es) a #

Methods

liftBaseWith :: (RunInBase (EffReader (IOE e) es) IO -> IO a) -> EffReader (IOE e) es a #

restoreM :: StM (EffReader (IOE e) es) a -> EffReader (IOE e) es a #

e :> es => MonadBase IO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

liftBase :: IO α -> EffReader (IOE e) es α #

e :> es => MonadFail (EffReader (Exception String e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

fail :: String -> EffReader (Exception String e) es a #

e :> es => MonadIO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

liftIO :: IO a -> EffReader (IOE e) es a #

Applicative (EffReader r es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

pure :: a -> EffReader r es a #

(<*>) :: EffReader r es (a -> b) -> EffReader r es a -> EffReader r es b #

liftA2 :: (a -> b -> c) -> EffReader r es a -> EffReader r es b -> EffReader r es c #

(*>) :: EffReader r es a -> EffReader r es b -> EffReader r es b #

(<*) :: EffReader r es a -> EffReader r es b -> EffReader r es a #

Functor (EffReader r es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

fmap :: (a -> b) -> EffReader r es a -> EffReader r es b #

(<$) :: a -> EffReader r es b -> EffReader r es a #

Monad (EffReader r es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

(>>=) :: EffReader r es a -> (a -> EffReader r es b) -> EffReader r es b #

(>>) :: EffReader r es a -> EffReader r es b -> EffReader r es b #

return :: a -> EffReader r es a #

e :> es => MonadUnliftIO (EffReader (IOE e) es) Source #

You probably want to use withEffToIO_ instead.

Instance details

Defined in Bluefin.Internal

Methods

withRunInIO :: ((forall a. EffReader (IOE e) es a -> IO a) -> IO b) -> EffReader (IOE e) es b #

type StM (EffReader (IOE e) es) a Source # 
Instance details

Defined in Bluefin.Internal

type StM (EffReader (IOE e) es) a = a

effReader :: (r -> Eff es a) -> EffReader r es a Source #

runEffReader :: r -> EffReader r es a -> Eff es a Source #

withEffToIO Source #

Arguments

:: e2 :> es 
=> ((forall r. (forall e1. IOE e1 -> Eff (e1 :& es) r) -> IO r) -> IO a)

Continuation with the unlifting function in scope.

-> IOE e2 
-> Eff es a 

Deprecated. Use withEffToIO_ instead.

withEffToIO' Source #

Arguments

:: e2 :> es 
=> IOE e2

Continuation with the unlifting function in scope.

-> ((forall r. (forall e1. IOE e1 -> Eff (e1 :& es) r) -> IO r) -> IO a) 
-> Eff es a 

withEffToIO_ Source #

Arguments

:: e :> es 
=> IOE e 
-> ((forall r. Eff es r -> IO r) -> IO a)

Continuation with the unlifting function in scope.

-> Eff es a 

This is equivalent to the withRunInIO method of MonadUnliftIO, but written in Bluefin-style.

withEffToIO_' Source #

Arguments

:: e2 :> es 
=> IOE e2 
-> ((forall r. (forall e1. IOE e1 -> Eff (e1 :& es) r) -> IO r) -> IO a)

Continuation with the unlifting function in scope.

-> Eff es a 

race :: e2 :> es => (forall e. IOE e -> Eff (e :& es) a) -> (forall e. IOE e -> Eff (e :& es) a) -> IOE e2 -> Eff es a Source #

connectCoroutines Source #

Arguments

:: forall es a b r. (forall e. Coroutine a b e -> Eff (e :& es) r) 
-> (forall e. a -> Coroutine b a e -> Eff (e :& es) r) 
-> Eff es r

͘

Connect two coroutines. Their execution is interleaved by exchanging as and bs. When the first yields its first a it starts the second (which is awaiting an a).

receiveStream :: (forall e. Consume a e -> Eff (e :& es) r) -> (forall e. Stream a e -> Eff (e :& es) r) -> Eff es r Source #

Old name for consumeStream. receiveStream will be deprecated in a future version.

consumeStream Source #

Arguments

:: (forall e. Consume a e -> Eff (e :& es) r)

Each await from the Consume ...

-> (forall e. Stream a e -> Eff (e :& es) r)

... receives the value yielded from the Stream

-> Eff es r 

zipCoroutines Source #

Arguments

:: e1 :> es 
=> Coroutine (a1, a2) b e1 
-> (forall e. Coroutine a1 b e -> Eff (e :& es) r) 
-> (forall e. Coroutine a2 b e -> Eff (e :& es) r) 
-> Eff es r

͘

hoistReader :: (forall b. m b -> n b) -> ReaderT r m a -> ReaderT r n a Source #

withMonadIO Source #

Arguments

:: e :> es 
=> IOE e 
-> (forall m. MonadIO m => m r)

MonadIO operation

-> Eff es r

MonadIO operation run in Eff

Run MonadIO operations in Eff.

>>> runEff_ $ \io -> withMonadIO io $ liftIO $ do
      putStrLn "Hello world!"
Hello, world!

withMonadFail Source #

Arguments

:: e :> es 
=> Exception String e

Exception to throw on fail

-> (forall m. MonadFail m => m r)

MonadFail operation

-> Eff es r

MonadFail operation run in Eff

Run MonadFail operations in Eff.

>>> runPureEff $ try $ \e ->
      when (2 > 1) $
        withMonadFail e (fail "2 was bigger than 1")
Left "2 was bigger than 1"

unsafeRemoveEff :: Eff (e :& es) a -> Eff es a Source #

This function is really very unsafe and for internal use only. Unlike the similarly-named unsafeEff_ function from effectful, which is provided for use in user code, this function must never be used in user code.

runPureEff :: (forall es. Eff es a) -> a Source #

Run an Eff that doesn't contain any unhandled effects.

weakenEff :: (t `In` t') -> Eff t r -> Eff t' r Source #

insertFirst :: Eff b r -> Eff (c1 :& b) r Source #

insertSecond :: Eff (c1 :& b) r -> Eff (c1 :& (c2 :& b)) r Source #

insertManySecond :: b :> c => Eff (c1 :& b) r -> Eff (c1 :& c) r Source #

assoc1Eff :: Eff ((a :& b) :& c) r -> Eff (a :& (b :& c)) r Source #

pushFirst :: Eff a r -> Eff (a :& b) r Source #

mergeEff :: Eff (a :& a) r -> Eff a r Source #

inContext :: e2 :> e1 => Eff (e1 :& e2) r -> Eff e1 r Source #

makeOp :: Eff (e :& e) r -> Eff e r Source #

Used to define dynamic effects.

useImpl :: e :> es => Eff e r -> Eff es r Source #

Used to define dynamic effects.

useImplUnder Source #

Arguments

:: e :> es 
=> Eff (e1 :& e) r 
-> Eff (e1 :& es) r

͘

Like useImpl

useImplIn Source #

Arguments

:: e :> es 
=> (t -> Eff (es :& e) r) 
-> t 
-> Eff es r

͘

Used to define handlers of compound effects.

useImplWithin Source #

Arguments

:: e :> es 
=> (t -> Eff (e1 :& e) r) 
-> t 
-> Eff (e1 :& es) r

͘

Deprecated. Use useImplUnder instead.

data StateSource (e :: Effects) Source #

Handle to a capability to create strict mutable state handles

Constructors

StateSource 

newtype Exception exn (e :: Effects) Source #

Handle to an exception of type exn

Constructors

UnsafeMkException (forall a. exn -> IO a) 

Instances

Instances details
Handle (Exception s) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Exception s e -> Exception s es Source #

e :> es => MonadFail (EffReader (Exception String e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

fail :: String -> EffReader (Exception String e) es a #

newtype State s (e :: Effects) Source #

A handle to a strict mutable state of type s

Constructors

UnsafeMkState (IORef s) 

Instances

Instances details
Handle (State s) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => State s e -> State s es Source #

newtype Coroutine a b (e :: Effects) Source #

A handle to a coroutine that yields values of type a and then expects values of type b.

Constructors

MkCoroutine (a -> Eff e b) 

Instances

Instances details
Handle (Coroutine a b) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Coroutine a b e -> Coroutine a b es Source #

type Stream a = Coroutine a () Source #

A handle to a stream that yields values of type a. It is implemented as a handle to a coroutine that yields values of type a and then expects values of type ().

type Consume a = Coroutine () a Source #

class Handle (h :: Effects -> Type) where Source #

You can define a Handle instance for your compound handles. As an example, an "application" handle with a dynamic effect for database queries, a concrete effect for application state and a concrete effect for a logging effect might look like this:

data Application e = MkApplication
  { queryDatabase :: forall e'. String -> Int -> Eff (e' :& e) [String],
    applicationState :: State (Int, Bool) e,
    logger :: Stream String e
  }

To define mapHandle for Application you should apply mapHandle to all the fields that are themeselves handles and apply useImplUnder to all the fields that are dynamic effects:

instance Handle Application where
  mapHandle
    MkApplication
      { queryDatabase = q,
        applicationState = a,
        logger = l
      } =
      MkApplication
        { queryDatabase = s i -> useImplUnder (q s i),
          applicationState = mapHandle a,
          logger = mapHandle l
        }

Methods

mapHandle :: e :> es => h e -> h es Source #

Used to create compound effects, i.e. handles that contain other handles.

Instances

Instances details
Handle IOE Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => IOE e -> IOE es Source #

Handle Application Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Application e -> Application es Source #

Handle Counter5 Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Counter5 e -> Counter5 es Source #

Handle Counter6 Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Counter6 e -> Counter6 es Source #

Handle Counter7 Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Counter7 e -> Counter7 es Source #

Handle FileSystem Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => FileSystem e -> FileSystem es Source #

Handle Handle Source # 
Instance details

Defined in Bluefin.Internal.System.IO

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Handle e -> Handle es Source #

Handle (Exception s) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Exception s e -> Exception s es Source #

Handle h => Handle (HandleReader h) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => HandleReader h e -> HandleReader h es Source #

Handle (Reader r) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Reader r e -> Reader r es Source #

Handle (State s) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => State s e -> State s es Source #

Handle (Writer w) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Writer w e -> Writer w es Source #

Handle (DynamicReader r) Source # 
Instance details

Defined in Bluefin.Internal.Examples

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => DynamicReader r e -> DynamicReader r es Source #

Handle (ConstEffect r :: Effects -> Type) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => ConstEffect r e -> ConstEffect r es Source #

Handle (Coroutine a b) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Coroutine a b e -> Coroutine a b es Source #

newtype In (a :: Effects) (b :: Effects) Source #

Constructors

In# (# #) 

merge :: (# #) -> (a :& a) `In` a Source #

eq :: (# #) -> a `In` a Source #

fstI :: (# #) -> a `In` (a :& b) Source #

sndI :: (# #) -> a `In` (b :& a) Source #

cmp :: (a `In` b) -> (b `In` c) -> a `In` c Source #

bimap :: (a `In` b) -> (c `In` d) -> (a :& c) `In` (b :& d) Source #

assoc1 :: (# #) -> ((a :& b) :& c) `In` (a :& (b :& c)) Source #

drop :: (a `In` b) -> a `In` (c :& b) Source #

here :: (a `In` b) -> a `In` (b :& c) Source #

w :: ((a :& b) `In` c) -> a `In` c Source #

w2 :: ((b :& a) `In` c) -> a `In` c Source #

b2 :: (a `In` b) -> (a :& c) `In` (b :& c) Source #

b :: (a `In` b) -> (c :& a) `In` (c :& b) Source #

subsume1 :: (e2 `In` e1) -> (e1 :& e2) `In` e1 Source #

subsume2 :: (e1 `In` e2) -> (e1 :& e2) `In` e2 Source #

class (es1 :: Effects) :> (es2 :: Effects) Source #

Effect subset constraint

Instances

Instances details
e :> e Source #

A set of effects e is a subset of itself

Instance details

Defined in Bluefin.Internal

e :> (e :& es) Source #

e is a subset of a larger set e :& es

Instance details

Defined in Bluefin.Internal

e :> es => e :> (x :& es) Source #

If e is subset of es then e is a subset of a larger set, x :& es

Instance details

Defined in Bluefin.Internal

throw Source #

Arguments

:: e :> es 
=> Exception ex e 
-> ex

Value to throw

-> Eff es a 
>>> runPureEff $ try $ \e -> do
      throw e 42
      pure "No exception thrown"
Left 42
>>> runPureEff $ try $ \e -> do
      pure "No exception thrown"
Right "No exception thrown"

has :: forall a b. a :> b => a `In` b Source #

data Dict c where Source #

Constructors

Dict :: forall c. c => Dict c 

have :: forall a b. (a `In` b) -> Dict (a :> b) Source #

try Source #

Arguments

:: forall exn (es :: Effects) a. (forall e. Exception exn e -> Eff (e :& es) a) 
-> Eff es (Either exn a)

Left if the exception was thrown, Right otherwise

>>> runPureEff $ try $ \e -> do
      throw e 42
      pure "No exception thrown"
Left 42

handle Source #

Arguments

:: forall exn (es :: Effects) a. (exn -> Eff es a)

If the exception is thrown, apply this handler

-> (forall e. Exception exn e -> Eff (e :& es) a) 
-> Eff es a 

handle, but with the argument order swapped

>>> runPureEff $ handle (pure . show) $ \e -> do
      throw e 42
      pure "No exception thrown"
"42"

catch Source #

Arguments

:: forall exn (es :: Effects) a. (forall e. Exception exn e -> Eff (e :& es) a) 
-> (exn -> Eff es a)

If the exception is thrown, apply this handler

-> Eff es a 

rethrowIO Source #

Arguments

:: forall ex es e1 e2 r. (e1 :> es, e2 :> es, Exception ex) 
=> IOE e1 
-> Exception ex e2 
-> Eff es r 
-> Eff es r

͘

Rethrow an exception raised by an IO action as a Bluefin exception.

runEff $ \io -> do
  r <- try $ \ex -> do
    rethrowIO @IOException io ex $ do
      effIO io (readFile "/tmp/doesnt-exist")

  effIO io $ putStrLn $ case r of
    Left e -> "Caught IOException:\n" ++ show e
    Right contents -> contents
Caught IOException:
/tmp/doesnt-exist: openFile: does not exist (No such file or directory)

bracket Source #

Arguments

:: Eff es a

Acquire the resource

-> (a -> Eff es ())

Release the resource

-> (a -> Eff es b)

Run the body

-> Eff es b 

bracket acquire release body: acquire a resource, perform the body with it, and release the resource even if body threw an exception. This is essentially the same as Control.Exception.bracket, whose documentation you can inspect for further details.

bracket has a very general type that does not require es to contain an exception or IO effect. The reason that this is safe is:

  • While bracket does catch exceptions, this is unobservable, since the exception is re-thrown; the cleanup action happens unconditionally; and no part of it gets access to the thrown exception.
  • Eff itself is able to guarantee that any exceptions thrown in the body will be actually thrown before bracket exits. This is inherited from the fact that Eff is a wrapper around IO.

While it is usually the case that the cleanup action will in fact want to use IO effects, this is not universally true, see the polymorphicBracket example for an example.

get Source #

Arguments

:: e :> es 
=> State s e 
-> Eff es s

The current value of the state

>>> runPureEff $ runState 10 $ \st -> do
      n <- get st
      pure (2 * n)
(20,10)

put Source #

Arguments

:: e :> es 
=> State s e 
-> s

The new value of the state. The new value is forced before writing it to the state.

-> Eff es () 

Set the value of the state

>>> runPureEff $ runState 10 $ \st -> do
      put st 30
((), 30)

modify Source #

Arguments

:: e :> es 
=> State s e 
-> (s -> s)

Apply this function to the state. The new value of the state is forced before writing it to the state.

-> Eff es () 
>>> runPureEff $ runState 10 $ \st -> do
      modify st (* 2)
((), 20)

withScopedException_ :: ((forall a. e -> IO a) -> IO r) -> IO (Either e r) Source #

withStateSource Source #

Arguments

:: (forall e. StateSource e -> Eff (e :& es) a) 
-> Eff es a

͘

runPureEff $ withStateSource $ \source -> do
  n <- newState source 5
  total <- newState source 0

  withJump $ \done -> forever $ do
    n' <- get n
    modify total (+ n')
    when (n' == 0) $ jumpTo done
    modify n (subtract 1)

  get total
15

newState Source #

Arguments

:: StateSource e 
-> s

The initial value for the state handle

-> Eff es (State s e)

A new state handle

runPureEff $ withStateSource $ \source -> do
  n <- newState source 5
  total <- newState source 0

  withJump $ \done -> forever $ do
    n' <- get n
    modify total (+ n')
    when (n' == 0) $ jumpTo done
    modify n (subtract 1)

  get total
15

runState Source #

Arguments

:: s

Initial state

-> (forall e. State s e -> Eff (e :& es) a)

Stateful computation

-> Eff es (a, s)

Result and final state

>>> runPureEff $ runState 10 $ \st -> do
      n <- get st
      pure (2 * n)
(20,10)

yieldCoroutine Source #

Arguments

:: e1 :> es 
=> Coroutine a b e1 
-> a

͘

-> Eff es b 

yield Source #

Arguments

:: e1 :> es 
=> Stream a e1 
-> a

Yield this value from the stream

-> Eff es () 

Yield an element to the stream.

>>> runPureEff $ yieldToList $ \y -> do
      yield y 1
      yield y 2
      yield y 100
([1,2,100], ())

handleCoroutine :: (a -> Eff es b) -> (z -> Eff es r) -> (forall e1. Coroutine a b e1 -> Eff (e1 :& es) z) -> Eff es r Source #

forEach Source #

Arguments

:: (forall e1. Coroutine a b e1 -> Eff (e1 :& es) r) 
-> (a -> Eff es b)

Apply this effectful function for each element of the coroutine

-> Eff es r 

Apply an effectful function to each element yielded to the stream.

>>> runPureEff $ yieldToList $ \y -> do
      for_ [0 .. 4] $ \i -> do
        yield y i
        yield y (i * 10)
([0, 0, 1, 10, 2, 20, 3, 30], ())

ignoreStream Source #

Arguments

:: (forall e1. Stream a e1 -> Eff (e1 :& es) r) 
-> Eff es r

͘

Ignore all elements yielded to the stream.

>>> runPureEff $ ignoreStream $ \y -> do
     for_ [0 .. 4] $ \i -> do
       yield y i
       yield y (i * 10)

     pure 42
42

inFoldable Source #

Arguments

:: (Foldable t, e1 :> es) 
=> t a

Yield all these values from the stream

-> Stream a e1 
-> Eff es () 
>>> runPureEff $ yieldToList $ inFoldable [1, 2, 100]
([1, 2, 100], ())

enumerate Source #

Arguments

:: e2 :> es 
=> (forall e1. Stream a e1 -> Eff (e1 :& es) r)

͘

-> Stream (Int, a) e2 
-> Eff es r 

Pair each element in the stream with an increasing index, starting from 0.

>>> runPureEff $ yieldToList $ enumerate (inFoldable ["A", "B", "C"])
([(0, "A"), (1, "B"), (2, "C")], ())

enumerateFrom Source #

Arguments

:: e2 :> es 
=> Int

Initial value

-> (forall e1. Stream a e1 -> Eff (e1 :& es) r) 
-> Stream (Int, a) e2 
-> Eff es r 

Pair each element in the stream with an increasing index, starting from an inital value.

>>> runPureEff $ yieldToList $ enumerateFrom1 (inFoldable ["A", "B", "C"])
([(1, "A"), (2, "B"), (3, "C")], ())

consumeEach Source #

Arguments

:: (forall e. Consume b e -> Eff (e :& es) r)

Body

-> Eff es b

Value to send to each await in the body.

-> Eff es r 

A version of forEach specialized to Consume. Every time the Consume is used to await a b, feed it the one created by the handler.

await :: e :> es => Consume a e -> Eff es a Source #

withEarlyReturn Source #

Arguments

:: (forall e. EarlyReturn r e -> Eff (e :& es) r) 
-> Eff es r

͘

Run an Eff action with the ability to return early to this point. In the language of exceptions, withEarlyReturn installs an exception handler for an exception of type r.

>>> runPureEff $ withEarlyReturn $ \e -> do
      for_ [1 .. 10] $ \i -> do
        when (i >= 5) $
          returnEarly e ("Returned early with " ++ show i)
      pure "End of loop"
"Returned early with 5"

returnEarly Source #

Arguments

:: e :> es 
=> EarlyReturn r e 
-> r

Return early to the handler, with this value.

-> Eff es a 
>>> runPureEff $ withEarlyReturn $ \e -> do
      for_ [1 .. 10] $ \i -> do
        when (i >= 5) $
          returnEarly e ("Returned early with " ++ show i)
      pure "End of loop"
"Returned early with 5"

evalState Source #

Arguments

:: s

Initial state

-> (forall e. State s e -> Eff (e :& es) a)

Stateful computation

-> Eff es a

Result

>>> runPureEff $ evalState 10 $ \st -> do
      n <- get st
      pure (2 * n)
20

withState Source #

Arguments

:: s

Initial state

-> (forall e. State s e -> Eff (e :& es) (s -> a))

Stateful computation

-> Eff es a

Result

>>> runPureEff $ withState 10 $ \st -> do
      n <- get st
      pure (s -> (2 * n, s))
(20,10)

data Compound e1 e2 ss where Source #

Constructors

Compound :: Proxy# s1 -> Proxy# s2 -> e1 s1 -> e2 s2 -> Compound e1 e2 (s1 :& s2) 

compound Source #

Arguments

:: h1 e1 
-> h2 e2

͘

-> Compound h1 h2 (e1 :& e2) 

inComp :: forall a b c r. a :> b => b :> c => (a :> c => r) -> r Source #

withCompound Source #

Arguments

:: forall h1 h2 e es r. e :> es 
=> Compound h1 h2 e 
-> (forall e1 e2. (e1 :> es, e2 :> es) => h1 e1 -> h2 e2 -> Eff es r)

͘

-> Eff es r 

withC1 :: forall e1 e2 ss es r. ss :> es => Compound e1 e2 ss -> (forall st. st :> es => e1 st -> Eff es r) -> Eff es r Source #

withC2 :: forall e1 e2 ss es r. ss :> es => Compound e1 e2 ss -> (forall st. st :> es => e2 st -> Eff es r) -> Eff es r Source #

putC :: forall ss es e. ss :> es => Compound e (State Int) ss -> Int -> Eff es () Source #

getC :: forall ss es e. ss :> es => Compound e (State Int) ss -> Eff es Int Source #

runCompound Source #

Arguments

:: e1 s1 
-> e2 s2

͘

-> (forall es'. Compound e1 e2 es' -> Eff (es' :& es) r) 
-> Eff (s1 :& (s2 :& es)) r 

yieldToList Source #

Arguments

:: (forall e1. Stream a e1 -> Eff (e1 :& es) r) 
-> Eff es ([a], r)

Yielded elements and final result

Gather all yielded elements into a list.

>>> runPureEff $ yieldToList $ \y -> do
      yield y 1
      yield y 2
      yield y 100
([1,2,100], ())

withYieldToList Source #

Arguments

:: (forall e. Stream a e -> Eff (e :& es) ([a] -> r))

Stream computation

-> Eff es r

Result

>>> runPureEff $ withYieldToList $ \y -> do
  yield y 1
  yield y 2
  yield y 100
  pure length
3

yieldToReverseList Source #

Arguments

:: (forall e. Stream a e -> Eff (e :& es) r) 
-> Eff es ([a], r)

Yielded elements in reverse order, and final result

This is more efficient than yieldToList because it gathers the elements into a stack in reverse order. yieldToList then reverses that stack.

>>> runPureEff $ yieldToReverseList $ \y -> do
      yield y 1
      yield y 2
      yield y 100
([100,2,1], ())

mapStream Source #

Arguments

:: e2 :> es 
=> (a -> b)

Apply this function to all elements of the input stream.

-> (forall e1. Stream a e1 -> Eff (e1 :& es) r)

Input stream

-> Stream b e2 
-> Eff es r 

mapMaybe Source #

Arguments

:: e2 :> es 
=> (a -> Maybe b)

Yield from the output stream all of the elemnts of the input stream for which this function returns Just

-> (forall e1. Stream a e1 -> Eff (e1 :& es) r)

Input stream

-> Stream b e2 
-> Eff es r 

catMaybes Source #

Arguments

:: e2 :> es 
=> (forall e1. Stream (Maybe a) e1 -> Eff (e1 :& es) r)

Input stream

-> Stream a e2 
-> Eff es r 

Remove Nothing elements from a stream.

withJump Source #

Arguments

:: (forall e. Jump e -> Eff (e :& es) ()) 
-> Eff es ()

͘

runPureEff $ withStateSource $ \source -> do
  n <- newState source 5
  total <- newState source 0

  withJump $ \done -> forever $ do
    n' <- get n
    modify total (+ n')
    when (n' == 0) $ jumpTo done
    modify n (subtract 1)

  get total
15

jumpTo Source #

Arguments

:: e :> es 
=> Jump e 
-> Eff es a

͘

runPureEff $ withStateSource $ \source -> do
  n <- newState source 5
  total <- newState source 0

  withJump $ \done -> forever $ do
    n' <- get n
    modify total (+ n')
    when (n' == 0) $ jumpTo done
    modify n (subtract 1)

  get total
15

unwrap :: e :> es => Jump e -> Maybe a -> Eff es a Source #

data IOE (e :: Effects) Source #

Handle that allows you to run IO operations

Constructors

MkIOE 

Instances

Instances details
Handle IOE Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => IOE e -> IOE es Source #

e :> es => MonadBaseControl IO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Associated Types

type StM (EffReader (IOE e) es) a #

Methods

liftBaseWith :: (RunInBase (EffReader (IOE e) es) IO -> IO a) -> EffReader (IOE e) es a #

restoreM :: StM (EffReader (IOE e) es) a -> EffReader (IOE e) es a #

e :> es => MonadBase IO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

liftBase :: IO α -> EffReader (IOE e) es α #

e :> es => MonadIO (EffReader (IOE e) es) Source # 
Instance details

Defined in Bluefin.Internal

Methods

liftIO :: IO a -> EffReader (IOE e) es a #

e :> es => MonadUnliftIO (EffReader (IOE e) es) Source #

You probably want to use withEffToIO_ instead.

Instance details

Defined in Bluefin.Internal

Methods

withRunInIO :: ((forall a. EffReader (IOE e) es a -> IO a) -> IO b) -> EffReader (IOE e) es b #

type StM (EffReader (IOE e) es) a Source # 
Instance details

Defined in Bluefin.Internal

type StM (EffReader (IOE e) es) a = a

effIO Source #

Arguments

:: e :> es 
=> IOE e 
-> IO a 
-> Eff es a

͘

Run an IO operation in Eff

>>> runEff_ $ \io -> do
      effIO io (putStrLn "Hello world!")
Hello, world!

runEff Source #

Arguments

:: (forall e es. IOE e -> Eff (e :& es) a) 
-> IO a

͘

Run an Eff whose only unhandled effect is IO.

>>> runEff_ $ \io -> do
      effIO io (putStrLn "Hello world!")
Hello, world!

We suggest you use runEff_ instead, as it probably has better type inference properties.

runEff_ Source #

Arguments

:: (forall e. IOE e -> Eff e a) 
-> IO a

͘

Run an Eff whose only unhandled effect is IO.

>>> runEff_ $ \io -> do
      effIO io (putStrLn "Hello world!")
Hello, world!

This probably has better type inference properties than runEff and so will probably replace it in a later version.

unsafeProvideIO Source #

Arguments

:: (forall e. IOE e -> Eff (e :& es) a) 
-> Eff es a

͘

connect :: (forall e1. Coroutine a b e1 -> Eff (e1 :& es) r1) -> (forall e2. a -> Coroutine b a e2 -> Eff (e2 :& es) r2) -> forall e1 e2. (e1 :> es, e2 :> es) => Eff es (Either (r1, a -> Coroutine b a e2 -> Eff es r2) (r2, b -> Coroutine a b e1 -> Eff es r1)) Source #

head' :: forall a b r es. (forall e. Coroutine a b e -> Eff (e :& es) r) -> forall e. e :> es => Eff es (Either r (a, b -> Coroutine a b e -> Eff es r)) Source #

newtype Writer w e Source #

Constructors

Writer (Stream w e) 

Instances

Instances details
Handle (Writer w) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Writer w e -> Writer w es Source #

runWriter Source #

Arguments

:: Monoid w 
=> (forall e. Writer w e -> Eff (e :& es) r)

͘

-> Eff es (r, w) 
>>> getAny $ snd $ runPureEff $ runWriter $ \w -> do
      -- Non-empty list (the tell event does happen)
      for_ [1 .. 10] $ \_ -> tell w (Any True)
True

execWriter Source #

Arguments

:: Monoid w 
=> (forall e. Writer w e -> Eff (e :& es) r)

͘

-> Eff es w 
>>> getAny $ runPureEff $ execWriter $ \w -> do
      -- Non-empty list (the tell event does happen)
      for_ [1 .. 10] $ \_ -> tell w (Any True)
True
>>> getAny $ runPureEff $ execWriter $ \w -> do
      -- Empty list (the tell event does not happen)
      for_ [] $ \_ -> tell w (Any True)
False

tell Source #

Arguments

:: e :> es 
=> Writer w e 
-> w

͘

-> Eff es () 
>>> getAny $ runPureEff $ execWriter $ \w -> do
      -- Non-empty list (the tell event does happen)
      for_ [1 .. 10] $ \_ -> tell w (Any True)
True

newtype Reader r e Source #

Constructors

MkReader (State r e) 

Instances

Instances details
Handle (Reader r) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => Reader r e -> Reader r es Source #

runReader Source #

Arguments

:: r

Initial value for Reader.

-> (forall e. Reader r e -> Eff (e :& es) a) 
-> Eff es a 

ask Source #

Arguments

:: e :> es 
=> Reader r e

͘

-> Eff es r 

Read the value. Note that ask has the property that these two operations are always equivalent:

do
  r1 <- ask re
  r2 <- ask re
  pure (r1, r2)
do
  r <- ask re
  pure (r, r)

asks Source #

Arguments

:: e :> es 
=> Reader r e 
-> (r -> a)

Read the value modified by this function

-> Eff es a 

Read the value modified by a function

local Source #

Arguments

:: e1 :> es 
=> Reader r e1 
-> (r -> r)

In the body, the reader value is modified by this function.

-> Eff es a

Body

-> Eff es a 

newtype HandleReader h e Source #

Constructors

UnsafeMkHandleReader (State (h e) e) 

Instances

Instances details
Handle h => Handle (HandleReader h) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => HandleReader h e -> HandleReader h es Source #

mapHandleReader Source #

Arguments

:: forall h e es. (Handle h, e :> es) 
=> HandleReader h e 
-> HandleReader h es

͘

localHandle Source #

Arguments

:: (e :> es, Handle h) 
=> HandleReader h e 
-> (h es -> h es) 
-> Eff es r 
-> Eff es r

͘

askHandle Source #

Arguments

:: (e :> es, Handle h) 
=> HandleReader h e 
-> Eff es (h es)

͘

runHandleReader Source #

Arguments

:: (e1 :> es, Handle h) 
=> h e1 
-> (forall e. HandleReader h e -> Eff (e :& es) r) 
-> Eff es r

͘

newtype ConstEffect r e Source #

Constructors

MkConstEffect r 

Instances

Instances details
Handle (ConstEffect r :: Effects -> Type) Source # 
Instance details

Defined in Bluefin.Internal

Methods

mapHandle :: forall (e :: Effects) (es :: Effects). e :> es => ConstEffect r e -> ConstEffect r es Source #

runConstEffect Source #

Arguments

:: r 
-> (forall e. ConstEffect r e -> Eff (e :& es) a) 
-> Eff es a

͘