Run
- Package
- purescript-run
- Repository
- natefaubion/purescript-run
#Run Source
newtype Run :: Row (Type -> Type) -> Type -> Type
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
Newtype (Run r a) _
Functor (Run r)
Apply (Run r)
Applicative (Run r)
Bind (Run r)
Monad (Run r)
MonadRec (Run r)
(TypeEquals (Proxy r1) (Proxy (EFFECT r2))) => MonadEffect (Run r1)
(TypeEquals (Proxy r1) (Proxy (RowApply AFF (RowApply EFFECT r2)))) => MonadAff (Run r1)
This will insert an
EFFECT
effect becauseMonadAff
entailsMonadEffect
. If you don't want this, useRun.liftAff
rather thanControl.Monad.Aff.Class.liftAff
.(TypeEquals (Proxy r1) (Proxy (RowApply CHOOSE r2))) => Alt (Run r1)
(TypeEquals (Proxy r1) (Proxy (RowApply CHOOSE r2))) => Plus (Run r1)
(TypeEquals (Proxy r1) (Proxy (RowApply CHOOSE r2))) => Alternative (Run r1)
#interpretRec Source
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.
#runAccumCont Source
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 Source
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.
#expand Source
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
Re-exports from Control.Monad.Rec.Class
Re-exports from Data.Functor.Variant
#VariantF Source
data VariantF :: Row (Type -> Type) -> Type -> Type
data VariantF f 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)
#onMatch Source
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.
#match Source
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
}
#default Source
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_ Source
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)
This instance is provided for compatibility, but is otherwise unnecessary. You can use monadic recursion with
Run
, deferring theMonadRec
constraint till it is interpretted.