From 9c0401bb47dee197ac79df3b83ff075479d54030 Mon Sep 17 00:00:00 2001 From: Mohammad Hasani Date: Tue, 30 Apr 2024 01:56:55 +0330 Subject: [PATCH] feat: change underlying rep of environment --- spago.dhall | 6 +- src/Control/Eff.purs | 168 +++++++++++++++++++++++------------ src/Control/Eff/Algebra.purs | 2 +- src/Control/Eff/Except.js | 16 ++-- src/Control/Eff/Except.purs | 61 ++++++++++--- src/Control/Eff/IO.purs | 28 +++--- src/Control/Eff/State.purs | 116 ++++++++++++++++++++++++ src/Control/Eff/Variant.purs | 97 +++++--------------- 8 files changed, 333 insertions(+), 161 deletions(-) create mode 100644 src/Control/Eff/State.purs diff --git a/spago.dhall b/spago.dhall index b9b6920..fa6d1b7 100644 --- a/spago.dhall +++ b/spago.dhall @@ -24,9 +24,13 @@ to generate this file without the comments in this block. , "transformers" , "typelevel-prelude" , "unsafe-coerce" + , "variant" + , "veither" + , "refs" + , "tuples" ] , packages = ./packages.dhall -, sources = [ "src/**/*.purs" ] +, sources = [ "src/**/*.purs", "test/**/*.purs" ] , license = "MPL-2.0" , repository = "https://github.com/the-dr-lazy/purescript-effectful" } diff --git a/src/Control/Eff.purs b/src/Control/Eff.purs index 179ab91..ef57ee3 100644 --- a/src/Control/Eff.purs +++ b/src/Control/Eff.purs @@ -1,7 +1,7 @@ {-| Module : Control.Eff Maintainer : Mohammad Hasani (the-dr-lazy.github.io) -Copyright : (c) 2021-2022 Effecful +Copyright : (c) 2021-2024 Effecful License : MPL 2.0 This Source Code Form is subject to the terms of the Mozilla Public @@ -10,29 +10,33 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. -} module Control.Eff - ( module Control.Eff.Algebra + ( Eff(..) , Environment - , Action(..) - , Eff(..) - , mk - , un - , unsafeMkFromAff + , Handler + , expand + , impose + , interpose , interpret - , intercept + , module Control.Eff.Algebra , reinterpret - , expand - , send , run + , send + , un + , unsafeMkFromAff + , addHandler ) where +import Control.Eff.Algebra import Prelude -import Control.Eff.Algebra import Control.Eff.Algebra as Eff -import Control.Eff.Variant as Eff -import Control.Eff.Variant as Eff.Variant +import Control.Eff.Variant (Variant) +import Control.Eff.Variant as Variant import Data.Symbol (class IsSymbol) import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Ref (Ref) +import Effect.Ref as Ref import Type.Proxy (Proxy) import Type.Row as Row import Unsafe.Coerce (unsafeCoerce) @@ -54,77 +58,123 @@ instance Applicative (Eff r) where instance Bind (Eff r) where bind (UnsafeMk m) f = UnsafeMk \environment -> do x <- m environment - un (f x) environment + un environment (f x) instance Monad (Eff r) -type Environment r = Eff.Variant r (Eff r) ~> Action r +type Handler :: Type +type Handler = forall a. Variant -> Aff a -data Action r a = Intercept (Environment r) (Eff r a) | Interpret (Eff r a) | Perform (Aff a) +type Environment :: Row Algebra -> Type +type Environment r = Ref Handler -mk :: forall r. Eff.Variant r (Eff r) ~> Eff r -mk f = UnsafeMk \environment -> do - case environment f of - Perform m -> m - Interpret (UnsafeMk m) -> m environment - Intercept env (UnsafeMk m) -> m env +-- mk :: forall r a. Variant -> Eff r a +-- mk f = UnsafeMk \m -> m f unsafeMkFromAff :: forall r. Aff ~> Eff r unsafeMkFromAff m = UnsafeMk \_ -> m -un :: forall r a. Eff r a -> Environment r -> Aff a -un (UnsafeMk m) = m +un :: forall r a. Environment r -> Eff r a -> Aff a +un ref (UnsafeMk m) = m ref + +type EffectHandler f fr = f (Eff fr) ~> Eff fr + +handle :: forall tag f r fr. IsSymbol tag => Row.Cons tag f r fr => Environment fr -> Proxy tag -> f (Eff fr) ~> Aff +handle environment ptag f = do + handler <- liftEffect $ Ref.read environment + + handler (Variant.inject ptag f) + +addHandler :: forall tag f r fr a. IsSymbol tag => Row.Cons tag f r fr => Environment r -> Proxy tag -> (f (Eff fr) a -> Eff fr a) -> Aff (Environment fr) +addHandler environment ptag handler = do + liftEffect $ Ref.modify_ (Variant.on ptag (un environment <<< handler)) (unsafeCoerce environment) + + pure (unsafeCoerce environment) + +getHandler :: forall tag f r fr a. IsSymbol tag => Row.Cons tag f r fr => Environment fr -> Proxy tag -> Aff (Eff fr a -> Eff r a) +getHandler environment ptag = do + handler <- liftEffect $ Ref.read environment + environment' <- liftEffect $ Ref.new (unsafeCoerce handler) + + pure $ \(UnsafeMk m) -> UnsafeMk \_ -> m environment' send - :: forall tag f r fr a + :: forall tag f r fr . IsSymbol tag => Functor (f (Eff fr)) => Row.Cons tag f r fr => Proxy tag - -> f (Eff fr) a - -> Eff fr a -send ptag f = mk (Eff.Variant.inject ptag f) + -> f (Eff fr) + ~> Eff fr +send ptag f = UnsafeMk \environment -> handle environment ptag f interpret - :: forall tag from r fromr - . Row.Cons tag from r fromr - => Functor (from (Eff fromr)) + :: forall tag f r fr + . Row.Cons tag f r fr + => Functor (f (Eff fr)) => IsSymbol tag => Proxy tag - -> (from (Eff fromr) ~> Eff fromr) - -> Eff fromr + -> EffectHandler f fr + -> Eff fr ~> Eff r interpret ptag interpreter (UnsafeMk m) = - UnsafeMk \environment -> - m (Eff.Variant.interpret ptag (Interpret <<< interpreter) (unsafeCoerce environment)) + UnsafeMk \r -> do + fr <- addHandler r ptag interpreter + m fr + +reinterpret + :: forall tag f r fr h a b + . Row.Cons tag f r fr + => IsSymbol tag + => Functor (f (Eff fr)) + => Proxy tag + -> (Eff h a -> Eff fr b) + -> EffectHandler f h + -> Eff fr a + -> Eff r b +reinterpret ptag run handler m = + (unsafeCoerce run) $ interpret ptag (unsafeCoerce handler) m -intercept - :: forall tag from r fromr - . Row.Cons tag from r fromr +interpose + :: forall tag f r fr a + . Row.Cons tag f r fr => IsSymbol tag - => Functor (from (Eff fromr)) + => Functor (f (Eff fr)) => Proxy tag - -> (from (Eff fromr) ~> Eff fromr) - -> Eff fromr - ~> Eff fromr -intercept ptag interceptor (UnsafeMk m) = - UnsafeMk \environment -> - m (Eff.Variant.intercept ptag (interceptor >>> Intercept environment) environment) + -> EffectHandler f fr + -> Eff fr a + -> Eff fr a +interpose ptag handler (UnsafeMk m) = + UnsafeMk \environment -> do + run <- getHandler environment ptag -expand :: forall from r fromr. Row.Union from r fromr => Eff from ~> Eff fromr -expand = unsafeCoerce + let + f :: f (Eff fr) a -> Eff r a + f = run <<< handler -reinterpret - :: forall tag from r tor fromr fromtor - . Row.Cons tag from r fromr - => Row.Cons tag from tor fromtor - => IsSymbol tag - => Functor (from (Eff fromtor)) + u :: f (Eff fr) a -> Eff fr a + u = unsafeCoerce + + _ <- addHandler environment ptag u + + m environment + +impose + :: forall tag f r fr h a b + . IsSymbol tag + => Row.Cons tag f r fr + => Functor (f (Eff fr)) => Proxy tag - -> (from (Eff fromtor) ~> Eff fromtor) - -> Eff fromr - ~> Eff tor -reinterpret ptag reinterpreter m = interpret ptag reinterpreter (unsafeCoerce m) + -> (Eff h a -> Eff fr b) + -> EffectHandler f h + -> Eff fr a + -> Eff fr b +impose ptag run handler m = (unsafeCoerce run) $ interpose ptag (unsafeCoerce handler) m + +expand :: forall from r fromr. Row.Union from r fromr => Eff from ~> Eff fromr +expand = unsafeCoerce -run :: forall a. Eff () a -> Aff a -run (UnsafeMk m) = m Eff.Variant.empty +run :: Eff () ~> Aff +run (UnsafeMk m) = do + ref <- liftEffect $ unsafeCoerce (Ref.new Variant.empty) + m ref diff --git a/src/Control/Eff/Algebra.purs b/src/Control/Eff/Algebra.purs index 05c377b..3dc189b 100644 --- a/src/Control/Eff/Algebra.purs +++ b/src/Control/Eff/Algebra.purs @@ -1,7 +1,7 @@ {-| Module : Control.Eff.Algebra Maintainer : Mohammad Hasani (the-dr-lazy.github.io) -Copyright : (c) 2021-2022 Effecful +Copyright : (c) 2021-2024 Effecful License : MPL 2.0 This Source Code Form is subject to the terms of the Mozilla Public diff --git a/src/Control/Eff/Except.js b/src/Control/Eff/Except.js index 5a68a22..2181896 100644 --- a/src/Control/Eff/Except.js +++ b/src/Control/Eff/Except.js @@ -1,6 +1,6 @@ /* * Maintainer : Mohammad Hasani (the-dr-lazy.github.io) - * Copyright : (c) 2021-2022 Effecful + * Copyright : (c) 2021-2024 Effecful * License : MPL 2.0 * * This Source Code Form is subject to the terms of the Mozilla Public @@ -8,18 +8,22 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +var _symbol = Symbol('Except') + exports.foreign_mkCustomError = function (r) { var e = new Error('Control.Eff.Except: unhandled exception (' + r.tag + ')') - e._tag = r.tag - e._value = r.value + + e[_symbol] = r return e } -exports.foreign_parseCustomError = function (r) { - if (r.error._tag !== r.tag) { +exports.foreign_parseCustomError = function (error) { + const r = e[_symbol] + + if (r !== undefined) { return null } - return r.error._value + return r } diff --git a/src/Control/Eff/Except.purs b/src/Control/Eff/Except.purs index 15daf51..adfc3e9 100644 --- a/src/Control/Eff/Except.purs +++ b/src/Control/Eff/Except.purs @@ -1,7 +1,7 @@ {-| Module : Control.Eff.Except Maintainer : Mohammad Hasani (the-dr-lazy.github.io) -Copyright : (c) 2021-2022 Effecful +Copyright : (c) 2021-2024 Effecful License : MPL 2.0 This Source Code Form is subject to the terms of the Mozilla Public @@ -11,18 +11,21 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. module Control.Eff.Except where -import Data.Either -import Data.Maybe import Prelude -import Type.Proxy import Control.Eff (Eff) import Control.Eff as Eff import Control.Monad.Error.Class (catchError, throwError) +import Data.Either (Either(..)) +import Data.Maybe (Maybe(..)) import Data.Nullable (Nullable) import Data.Nullable as Nullable import Data.Symbol (class IsSymbol, reflectSymbol) +import Data.Variant (Variant) +import Data.Variant.Internal (VariantRep(..)) +import Data.Veither (Veither(..)) import Effect.Exception (Error) +import Type.Proxy (Proxy(..)) import Type.Row (type (+)) import Type.Row as Row import Unsafe.Coerce (unsafeCoerce) @@ -56,13 +59,24 @@ catchAs -> Eff (Except es + r) a -> Eff (Except s + r) a catchAs ptag handler (Eff.UnsafeMk m) = Eff.UnsafeMk \environment -> - m (unsafeCoerce environment) `catchError` \error -> case parseCustomError ptag error of - Just e -> Eff.un (handler e) environment + m (unsafeCoerce environment) `catchError` \error -> case parseCustomErrorAs ptag error of + Just e -> Eff.un environment (handler e) Nothing -> throwError error catch :: forall e s r a. (e -> Eff (Except s + r) a) -> Eff (Except (error :: e | s) + r) a -> Eff (Except s + r) a catch = catchAs (Proxy :: Proxy "error") +catchAll + :: forall es r fr a + . Row.Cons "except" (ExceptF es) r fr + => (Variant es -> Eff r a) + -> Eff fr a + -> Eff r a +catchAll handler (Eff.UnsafeMk m) = Eff.UnsafeMk \environment -> + m (unsafeCoerce environment) `catchError` \error -> case parseCustomError error of + Just e -> Eff.un environment (handler e) + Nothing -> throwError error + tryAs :: forall tag e s es r a . Row.Cons tag e s es @@ -75,6 +89,14 @@ tryAs ptag m = catchAs ptag (pure <<< Left) (Right <$> m) try :: forall e s r a. Eff (Except (error :: e | s) + r) a -> Eff (Except s + r) (Either e a) try = tryAs (Proxy :: Proxy "error") +tryAll + :: forall es r a + . Eff (Except es + r) a + -> Eff r (Veither es a) +tryAll m = catchAll (pure <<< Veither <<< unsafeExpand) (pure <$> m) + where + unsafeExpand = unsafeCoerce :: forall r1 r2. Variant r1 -> Variant r2 + noteAs :: forall tag e s es r a . Row.Cons tag e s es @@ -104,12 +126,31 @@ rethrowAs ptag = case _ of rethrow :: forall e s r a. Either e a -> Eff (Except (error :: e | s) + r) a rethrow = rethrowAs (Proxy :: Proxy "error") +-- vrethrow :: forall es r a. Veither es a -> Eff (Except es + r) a +-- vrethrow = + run :: forall r. Eff (Except () + r) ~> Eff r run = unsafeCoerce -foreign import foreign_mkCustomError :: forall es. { tag :: String, value :: es } -> Error +type X e = { tag :: String, value :: e } + +foreign import foreign_mkCustomError :: forall e. X e -> Error + +foreign import foreign_parseCustomError :: forall e. Error -> Nullable (X e) + +parseCustomError :: forall es. Error -> Maybe (Variant es) +parseCustomError error = toVariant <$> Nullable.toMaybe (foreign_parseCustomError error) + where + toVariant :: forall a. X a -> Variant es + toVariant e = unsafeCoerce (VariantRep { type: e.tag, value: e.value }) -foreign import foreign_parseCustomError :: forall es. { tag :: String, error :: Error } -> Nullable es +parseCustomErrorAs :: forall tag e. IsSymbol tag => Proxy tag -> Error -> Maybe e +parseCustomErrorAs ptag error = parseCustomError error >>= prj ptag + where + prj :: forall p r. IsSymbol p => Proxy p -> Variant r -> Maybe e + prj p r = case coerceV r of + VariantRep v | v.type == reflectSymbol p -> Just v.value + _ -> Nothing -parseCustomError :: forall tag es. IsSymbol tag => Proxy tag -> Error -> Maybe es -parseCustomError ptag error = Nullable.toMaybe (foreign_parseCustomError { tag: reflectSymbol ptag, error }) + coerceV :: forall r. Variant r -> VariantRep e + coerceV = unsafeCoerce diff --git a/src/Control/Eff/IO.purs b/src/Control/Eff/IO.purs index 85243b6..b92ff6c 100644 --- a/src/Control/Eff/IO.purs +++ b/src/Control/Eff/IO.purs @@ -1,7 +1,7 @@ {-| Module : Control.Eff.IO Maintainer : Mohammad Hasani (the-dr-lazy.github.io) -Copyright : (c) 2021-2022 Effecful +Copyright : (c) 2021-2024 Effecful License : MPL 2.0 This Source Code Form is subject to the terms of the Mozilla Public @@ -9,15 +9,22 @@ License, version 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -} -module Control.Eff.IO ( - IOF(..), IO, tag, run, class Lift, lift) where +module Control.Eff.IO + ( IOF(..) + , IO + , tag + , run + , class Lift + , lift + ) where -import Control.Eff (Eff) -import Control.Eff as Eff -import Control.Eff.Variant as Eff.Variant import Prelude import Type.Proxy import Type.Row + +import Control.Eff (Eff) +import Control.Eff as Eff +import Control.Eff.Variant as Variant import Effect (Effect) import Effect.Aff (Aff) import Effect.Class (liftEffect) @@ -33,12 +40,13 @@ derive newtype instance Functor (IOF m) type IO :: Row Eff.Algebra -> Row Eff.Algebra type IO r = (io :: IOF | r) -perform :: forall m r. IOF m ~> Eff.Action r -perform (IO m) = Eff.Perform m +perform :: forall m r. IOF m ~> Aff +perform (IO m) = m run :: forall r. Eff (IO + r) ~> Eff r -run (Eff.UnsafeMk m) = Eff.UnsafeMk \environment -> - m (Eff.Variant.interpret tag perform (unsafeCoerce environment)) +run (Eff.UnsafeMk m) = Eff.UnsafeMk \r -> do + ior <- Eff.addHandler r tag (Eff.unsafeMkFromAff <<< perform) + m ior class Lift m where lift :: forall r. m ~> Eff (IO + r) diff --git a/src/Control/Eff/State.purs b/src/Control/Eff/State.purs new file mode 100644 index 0000000..0b69b5e --- /dev/null +++ b/src/Control/Eff/State.purs @@ -0,0 +1,116 @@ +{-| +Module : Control.Eff.State +Maintainer : Mohammad Hasani (the-dr-lazy.github.io) +Copyright : (c) 2021-2024 Effecful +License : MPL 2.0 + +This Source Code Form is subject to the terms of the Mozilla Public +License, version 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +-} + +module Control.Eff.State where + +import Prelude + +import Control.Eff (Eff(..)) +import Control.Eff as Eff +import Control.Eff.Variant as Variant +import Data.Symbol (class IsSymbol) +import Data.Tuple (Tuple, snd) +import Data.Tuple.Nested ((/\)) +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Ref (Ref) +import Effect.Ref as Ref +import Effect.Unsafe (unsafePerformEffect) +import Type.Proxy (Proxy(..)) +import Type.Row (type (+)) +import Type.Row as Row +import Unsafe.Coerce (unsafeCoerce) + +data StateF :: Type -> Eff.Algebra +data StateF s m a = State + +derive instance Functor m => Functor (StateF s m) + +type State :: Type -> Row Eff.Algebra -> Row Eff.Algebra +type State s r = (state :: StateF s | r) + +tag = Proxy :: Proxy "state" + +getAs :: forall tag s q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> Eff r s +getAs tag = UnsafeMk \r -> do + handler <- liftEffect $ Ref.read r + handler (Variant.inject tag State) + +get :: forall s r. Eff (State s + r) s +get = getAs tag + +getsAs :: forall tag s t q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> (s -> t) -> Eff r t +getsAs tag f = f <$> getAs tag + +gets :: forall s t r. (s -> t) -> Eff (State s + r) t +gets = getsAs tag + +putAs :: forall tag s r fr. IsSymbol tag => Row.Cons tag (StateF s) r fr => Proxy tag -> s -> Eff fr Unit +putAs tag s = UnsafeMk \fr -> + liftEffect $ Ref.modify_ (Variant.on tag (\_ -> pure s :: Aff s)) (unsafeCoerce fr) + +put :: forall s r. s -> Eff (State s + r) Unit +put = putAs tag + +stateAs :: forall tag s a q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> (s -> Tuple s a) -> Eff r a +stateAs tag f = do + s <- getAs tag + let s' /\ a = f s + putAs tag s' + pure a + +state :: forall s a r. (s -> Tuple s a) -> Eff (State s + r) a +state = stateAs tag + +modifyAs :: forall tag s q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> (s -> s) -> Eff r Unit +modifyAs tag f = stateAs tag (\s -> f s /\ unit) + +modify + :: forall s r. (s -> s) -> Eff (State s + r) Unit +modify = modifyAs tag + +stateMAs :: forall tag s a q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> (s -> Eff r (Tuple s a)) -> Eff r a +stateMAs tag f = do + s <- getAs tag + s' /\ a <- f s + putAs tag s + pure a + +stateM :: forall s a r. (s -> Eff (State s + r) (Tuple s a)) -> Eff (State s + r) a +stateM = stateMAs tag + +modifyMAs :: forall tag s q r. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> (s -> Eff r s) -> Eff r Unit +modifyMAs tag f = stateMAs tag \s -> map (_ /\ unit) (f s) + +modifyM + :: forall s r. (s -> Eff (State s + r) s) -> Eff (State s + r) Unit +modifyM = modifyMAs tag + +runAs :: forall tag s r fr a. IsSymbol tag => Row.Cons tag (StateF s) r fr => Proxy tag -> s -> Eff fr a -> Eff r (Tuple s a) +runAs tag s m = coerce do + putAs tag s + a <- m + s <- getAs tag + + pure $ s /\ a + + where + coerce :: forall a. Eff fr a -> Eff r a + coerce = unsafeCoerce + +run :: forall s r a. s -> Eff (State s + r) a -> Eff r (Tuple s a) +run = runAs tag + +evalAs :: forall tag s q r a. IsSymbol tag => Row.Cons tag (StateF s) q r => Proxy tag -> s -> Eff r a -> Eff q a +evalAs tag s f = map snd (runAs tag s f) + +eval :: forall s r. s -> Eff (State s + r) ~> Eff r +eval = evalAs tag diff --git a/src/Control/Eff/Variant.purs b/src/Control/Eff/Variant.purs index 7b24e3e..5266f9d 100644 --- a/src/Control/Eff/Variant.purs +++ b/src/Control/Eff/Variant.purs @@ -1,7 +1,7 @@ {-| Module : Control.Eff.Variant Maintainer : Mohammad Hasani (the-dr-lazy.github.io) -Copyright : (c) 2021-2022 Effecful +Copyright : (c) 2021-2024 Effecful License : MPL 2.0 This Source Code Form is subject to the terms of the Mozilla Public @@ -12,6 +12,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. module Control.Eff.Variant where import Prelude + import Control.Eff.Algebra (Algebra) import Data.Symbol (class IsSymbol, reflectSymbol) import Partial.Unsafe (unsafeCrashWith) @@ -19,93 +20,41 @@ import Type.Proxy (Proxy) import Type.Row as Row import Unsafe.Coerce (unsafeCoerce) -data Variant :: Row Algebra -> (Type -> Type) -> Type -> Type -data Variant r m a +data Variant :: Type +data Variant -newtype VariantRep :: Algebra -> (Type -> Type) -> Type -> Type -newtype VariantRep f m a = VariantRep +newtype VariantRep :: Type -> Type +newtype VariantRep a = VariantRep { tag :: String - , value :: f m a - , map :: forall x y. (x -> y) -> f m x -> f m y + , value :: a } -instance Functor (Variant r m) where - map f a = - case coerceY a of - VariantRep v -> coerceV $ VariantRep - { tag: v.tag - , value: v.map f v.value - , map: v.map - } - where - coerceY :: forall f a. Variant r m a -> VariantRep f m a - coerceY = unsafeCoerce - - coerceV :: forall f a. VariantRep f m a -> Variant r m a - coerceV = unsafeCoerce - inject - :: forall tag f r fr m a - . Row.Cons tag f r fr - => IsSymbol tag - => Functor (f m) + :: forall tag a + . IsSymbol tag => Proxy tag - -> f m a - -> Variant fr m a -inject ptag value = coerceV $ VariantRep { tag: reflectSymbol ptag, value, map } + -> a + -> Variant +inject ptag value = coerceV $ VariantRep { tag: reflectSymbol ptag, value } where - coerceV :: VariantRep f m a -> Variant fr m a + coerceV :: VariantRep a -> Variant coerceV = unsafeCoerce -interpret - :: forall tag f r fr m a b - . Row.Cons tag f r fr - => IsSymbol tag +on + :: forall tag a b + . IsSymbol tag => Proxy tag - -> (f m a -> b) - -> (Variant r m a -> b) - -> (Variant fr m a -> b) -interpret ptag f g r = + -> (a -> b) + -> (Variant -> b) + -> (Variant -> b) +on ptag f g r = case coerceY r of VariantRep v | v.tag == reflectSymbol ptag -> f v.value - _ -> g (coerceR r) + _ -> g r where - coerceY :: Variant fr m a -> VariantRep f m a + coerceY :: Variant -> VariantRep a coerceY = unsafeCoerce - coerceR :: Variant fr m a -> Variant r m a - coerceR = unsafeCoerce - -intercept - :: forall tag f r fr m a b - . Row.Cons tag f r fr - => IsSymbol tag - => Proxy tag - -> (f m a -> b) - -> (Variant fr m a -> b) - -> (Variant fr m a -> b) -intercept ptag f g r = - case coerceY r of - VariantRep v | v.tag == reflectSymbol ptag -> f v.value - _ -> g (coerceR r) - where - coerceY :: Variant fr m a -> VariantRep f m a - coerceY = unsafeCoerce - - coerceR :: Variant fr m a -> Variant fr m a - coerceR = unsafeCoerce - -reinterpret - :: forall tag tag' f g r fr gr m a b - . Row.Cons tag f r fr - => Row.Cons tag' g r gr - => IsSymbol tag - => Proxy tag - -> (f m a -> b) - -> (Variant fr m a -> b) - -> (Variant gr m a -> b) -reinterpret = unsafeCoerce 1 - -empty :: forall m a b. Variant () m a -> b +empty :: forall a. Variant -> a empty r = unsafeCrashWith case unsafeCoerce r of VariantRep v -> "Control.Eff.Variant: pattern match failure [" <> v.tag <> "]"