Module

Run

Package
purescript-run
Repository
natefaubion/purescript-run

#Run Source

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 ∷ STATE Int
  , except ∷ EXCEPT String
  , effect ∷ 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_
    ∷ ∀ 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 Source

lift :: forall a f r2 r1 sym. Cons sym (FProxy f) r1 r2 => IsSymbol sym => Functor f => SProxy sym -> f a -> Run r2 a

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

#send Source

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

Enqueues an instruction in the Run Monad.

#extract Source

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

Extracts the value from a purely interpreted program.

#interpret Source

interpret :: forall r a m. 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 Source

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

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

#run Source

run :: forall r a m. 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 Source

runRec :: forall r a m. 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 Source

runCont :: forall r b a m. (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 Source

runPure :: forall a r2 r1. (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 Source

runAccum :: forall a s r m. 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 Source

runAccumRec :: forall a s r m. 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 Source

runAccumCont :: forall b a s r m. (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 Source

runAccumPure :: forall s b a r2 r1. (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 Source

peel :: forall r a. 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 Source

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

Eliminator for the Run data type.

#expand Source

expand :: forall a rx r2 r1. 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 Source

type EFFECT = FProxy Effect

Type synonym for using Effect as an effect.

#AFF Source

type AFF = FProxy Aff

Type synonym for using Aff as an effect.

#liftEffect Source

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

#liftAff Source

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

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

#runBaseEffect Source

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

Runs a base Effect effect.

#runBaseAff Source

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

Runs a base Aff effect.

#runBaseAff' Source

runBaseAff' :: (Run (aff :: AFF, effect :: 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

  • Loop a
  • Done b

Instances

  • Functor (Step a)
  • Bifunctor Step

Re-exports from Data.Functor.Variant

#VariantF

data VariantF (f :: Row Type) a

Instances

  • Functor (VariantF r)
  • (RowToList row rl, FoldableVFRL rl row) => Foldable (VariantF row)
  • (RowToList row rl, TraversableVFRL rl row) => Traversable (VariantF row)
  • (RowToList r rl, VariantTags rl, VariantFShows rl a, Show a) => Show (VariantF r a)

#FProxy

data FProxy (a :: Type -> Type)

Proxy for a Functor.

Constructors

  • FProxy

#onMatch

onMatch :: forall b a r3 r2 r1 r rl. 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 r2 r1 b a f sym. Cons sym (FProxy f) r1 r2 => IsSymbol sym => SProxy 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 b a r2 r1 r rl. 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 :: FProxy Maybe, bar :: FProxy (Tuple String), baz :: FProxy (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 r2 r1 a f sym. Cons sym (FProxy f) r1 r2 => IsSymbol sym => Functor f => SProxy sym -> f a -> VariantF r2 a

Inject into the variant at a given label.

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

#default

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

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

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

#case_

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

Combinator for exhaustive pattern matching.

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

Re-exports from Data.Symbol

#SProxy Source

data SProxy (sym :: Symbol)

A value-level proxy for a type-level symbol.

Constructors