Module

Run

#Run

newtype Run r a

An extensible effect Monad, indexed by a set of effect functors. Effects are eliminated by interpretation into a pure value or into some base effect Monad.

An example using State and Except:

type MyEffects =
  ( STATE Int
  + EXCEPT String
  + EFFECT
  + ()
  )

yesProgram :: Run MyEffects Unit
yesProgram = do
  whenM (gets (_ < 0)) do
    throw "Number is less than 0"
  whileM_ (gets (_ > 0)) do
    liftEffect $ log "Yes"
    modify (_ - 1)
  where
  whileM_
    :: forall a
    . Run MyEffects Boolean
    -> Run MyEffects a
    -> Run MyEffects Unit
  whileM_ mb ma = flip tailRecM unit \a ->
    mb >>= if _ then ma $> Loop unit else pure $ Done unit

main =
  yesProgram
    # catch (liftEffect <<< log)
    # runState 10
    # runBaseEffect
    # void

Constructors

Instances

#lift

lift :: forall proxy sym r1 r2 f a. Cons sym f r1 r2 => IsSymbol sym => Functor f => proxy sym -> f a -> Run r2 a

Lifts an effect functor into the Run Monad according to the provided Proxy slot.

#send

send :: forall a r. VariantF r a -> Run r a

Enqueues an instruction in the Run Monad.

#extract

extract :: forall a. Run () a -> a

Extracts the value from a purely interpreted program.

#interpret

interpret :: forall m a r. Monad m => ((VariantF r) ~> m) -> Run r a -> m a

Extracts the value from a program via some Monad m. This assumes stack safety under Monadic recursion.

#interpretRec

interpretRec :: forall m a r. MonadRec m => ((VariantF r) ~> m) -> Run r a -> m a

Extracts the value from a program via some MonadRec m, preserving stack safety.

#run

run :: forall m a r. Monad m => (VariantF r (Run r a) -> m (Run r a)) -> Run r a -> m a

Identical to interpret but with a less restrictive type signature, letting you intercept the rest of the program.

#runRec

runRec :: forall m a r. MonadRec m => (VariantF r (Run r a) -> m (Run r a)) -> Run r a -> m a

Identical to interpretRec but with a less restrictive type signature, letting you intercept the rest of the program.

#runCont

runCont :: forall m a b r. (VariantF r (m b) -> m b) -> (a -> m b) -> Run r a -> m b

Extracts the value from a program via some m using continuation passing.

#runPure

runPure :: forall r1 r2 a. (VariantF r1 (Run r1 a) -> Step (Run r1 a) (VariantF r2 (Run r1 a))) -> Run r1 a -> Run r2 a

Eliminates effects purely. Uses Step from Control.Monad.Rec.Class to preserve stack safety under tail recursion.

#runAccum

runAccum :: forall m r s a. Monad m => (s -> VariantF r (Run r a) -> m (Tuple s (Run r a))) -> s -> Run r a -> m a

Extracts the value from a program via some Monad m with an internal accumulator. This assumes stack safety under Monadic recursion.

#runAccumRec

runAccumRec :: forall m r s a. MonadRec m => (s -> VariantF r (Run r a) -> m (Tuple s (Run r a))) -> s -> Run r a -> m a

Extracts the value from a program via some MonadRec m with an internal accumulator.

#runAccumCont

runAccumCont :: forall m r s a b. (s -> VariantF r (s -> m b) -> m b) -> (s -> a -> m b) -> s -> Run r a -> m b

Extracts the value from a program via some m using continuation passing with an internal accumulator.

#runAccumPure

runAccumPure :: forall r1 r2 a b s. (s -> VariantF r1 (Run r1 a) -> Step (Tuple s (Run r1 a)) (VariantF r2 (Run r1 a))) -> (s -> a -> b) -> s -> Run r1 a -> Run r2 b

Eliminates effects purely with an internal accumulator. Uses Step from Control.Monad.Rec.Class to preserve stack safety under tail recursion.

#peel

peel :: forall a r. Run r a -> Either (VariantF r (Run r a)) a

Reflects the next instruction or the final value if there are no more instructions.

#resume

resume :: forall a b r. (VariantF r (Run r a) -> b) -> (a -> b) -> Run r a -> b

Eliminator for the Run data type.

#expand

expand :: forall r1 r2 rx a. Union r1 rx r2 => Run r1 a -> Run r2 a

Casts some set of effects to a wider set of effects via a left-biased union. For example, you could take a closed effect and unify it with a superset of effects because we know the additional effects never occur.

type LessRows = (foo :: Foo)
type MoreRows = (foo :: Foo, bar :: Bar, baz :: Baz)

foo :: Run LessRows Unit
foo = foo

foo' :: Run MoreRows Unit
foo' = expand foo

#EFFECT

type EFFECT r = (effect :: Effect | r)

Type synonym for using Effect as an effect.

#AFF

type AFF r = (aff :: Aff | r)

Type synonym for using Aff as an effect.

#liftEffect

liftEffect :: forall r. Effect ~> (Run (EFFECT + r))

#liftAff

liftAff :: forall r. Aff ~> (Run (AFF + r))

Lift an Aff effect into the Run Monad via the aff label.

#runBaseEffect

runBaseEffect :: (Run (EFFECT + ())) ~> Effect

Runs a base Effect effect.

#runBaseAff

runBaseAff :: (Run (AFF + ())) ~> Aff

Runs a base Aff effect.

#runBaseAff'

runBaseAff' :: (Run (AFF + EFFECT + ())) ~> Aff

Runs base Aff and Effect together as one effect.

Re-exports from Control.Monad.Rec.Class

#Step

data Step a b

The result of a computation: either Loop containing the updated accumulator, or Done containing the final result of the computation.

Constructors

Instances

Re-exports from Data.Functor.Variant

#VariantF

data VariantF f a

Instances

#onMatch

onMatch :: forall rl r r1 r2 r3 a b. RowToList r rl => VariantFMatchCases rl r1 a b => Union r1 r2 r3 => Record r -> (VariantF r2 a -> b) -> VariantF r3 a -> b

Match a VariantF with a Record containing functions for handling cases. This is similar to on, except instead of providing a single label and handler, you can provide a record where each field maps to a particular VariantF case.

onMatch
 { foo: \foo -> "Foo: " <> maybe "nothing" id foo
 , bar: \bar -> "Bar: " <> snd bar
 }

Polymorphic functions in records (such as show or id) can lead to inference issues if not all polymorphic variables are specified in usage. When in doubt, label methods with specific types, such as show :: Int -> String, or give the whole record an appropriate type.

#on

on :: forall proxy sym f a b r1 r2. Cons sym f r1 r2 => IsSymbol sym => proxy sym -> (f a -> b) -> (VariantF r1 a -> b) -> VariantF r2 a -> b

Attempt to read a variant at a given label by providing branches. The failure branch receives the provided variant, but with the label removed.

#match

match :: forall rl r r1 r2 a b. RowToList r rl => VariantFMatchCases rl r1 a b => Union r1 () r2 => Record r -> VariantF r2 a -> b

Combinator for exhaustive pattern matching using an onMatch case record.

matchFn :: VariantF (foo :: Maybe, bar :: Tuple String, baz :: Either String) Int -> String
matchFn = match
 { foo: \foo -> "Foo: " <> maybe "nothing" show foo
 , bar: \bar -> "Bar: " <> show (snd bar)
 , baz: \baz -> "Baz: " <> either id show baz
 }

#inj

inj :: forall proxy sym f a r1 r2. Cons sym f r1 r2 => IsSymbol sym => Functor f => proxy sym -> f a -> VariantF r2 a

Inject into the variant at a given label.

maybeAtFoo :: forall r. VariantF (foo :: Maybe | r) Int
maybeAtFoo = inj (Proxy :: Proxy "foo") (Just 42)

#default

default :: forall a b r. a -> VariantF r b -> a

Combinator for partial matching with a default value in case of failure.

caseFn :: forall r. VariantF (foo :: Maybe, bar :: Tuple String | r) Int -> String
caseFn = default "No match"
 # on (Proxy :: Proxy "foo") (\foo -> "Foo: " <> maybe "nothing" show foo)
 # on (Proxy :: Proxy "bar") (\bar -> "Bar: " <> show (snd bar))

#case_

case_ :: forall a b. VariantF () a -> b

Combinator for exhaustive pattern matching.

caseFn :: VariantF (foo :: Maybe, bar :: Tuple String, baz :: Either String) Int -> String
caseFn = case_
 # on (Proxy :: Proxy "foo") (\foo -> "Foo: " <> maybe "nothing" show foo)
 # on (Proxy :: Proxy "bar") (\bar -> "Bar: " <> show (snd bar))
 # on (Proxy :: Proxy "baz") (\baz -> "Baz: " <> either id show baz)

Modules