| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Capability.Reflection
Contents
Description
Use this module to provide an ad-hoc interpreter for a capability using type class reflection.
Use the functions interpret_ or interpret for ad-hoc interpretation of
capabilities.
Refer to Reflected if you would like to enable reflection for a new
capability.
More complex examples using this module can be found in the Reflection example module.
For details on reflection refer to the tutorial at
https://www.tweag.io/posts/2017-12-21-reflection-tutorial.html and the
reflection library at https://hackage.haskell.org/package/reflection.
Synopsis
- interpret_ :: forall tag c m a. (Monad m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. c m' => m' a) -> m a
- interpret :: forall tag (cs :: [Capability]) c m a. (Monad m, All cs m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. All (c ': cs) m' => m' a) -> m a
- data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
- newtype Reflected (s :: Type) (c :: Capability) (m :: Type -> Type) (a :: Type) = Reflect (m a)
- reified :: forall s tag c m. Reifies s (Reified tag c m) => Reified tag c m
- class Reifies (s :: k) a | s -> a
- reify :: a -> (forall s. Reifies s a => Proxy s -> r) -> r
- reflect :: Reifies s a => proxy s -> a
- data Proxy (t :: k) = Proxy
Reflection
interpret_ :: forall tag c m a. (Monad m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. c m' => m' a) -> m a Source #
interpret_ @tag dict action
Execute action using the ad-hoc interpretation of a capability c under
tag defined by dict, where dict is a value of type ,
i.e. a record providing the implementation of the methods of capability Reified tag cc.
For example, the following provides an ad-hoc interpretation for the
HasSource capability.
>>>:{interpret_ @"my-source" ReifiedSource { _await = pure "capabilities" } (replicateM 3 (await @"my-source")) :} ["capabilities", "capabilities", "capabilities"]
interpret :: forall tag (cs :: [Capability]) c m a. (Monad m, All cs m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. All (c ': cs) m' => m' a) -> m a Source #
interpret @tag @ambient dict action
Like interpret_ but forwards the ambient capabilities ambient into the
context of action as well.
For example, the following provides an ad-hoc interpretation for the
HasSource capability, while using an ambient
HasSink capability.
>>>:{interpret @"my-source" @'[HasSink "my-sink" String] ReifiedSource { _await = pure "capabilities" } (replicateM_ 3 (await @"my-source" >>= yield @"my-sink")) :}
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type) Source #
Reified tag capability m
Defines the dictionary type for the methods of capability under tag in
the monad m. Refer to interpret_ for an example use-case.
For example, the HasSink capability has the method
. The corresponding dictionary type is
defined as follows.yield :: a -> m ()
>>>:{data instance Reified tag (HasSink tag a) m = ReifiedSink { _yield :: forall a. a -> m () } :}
Superclass dictionaries are represented as nested records. For example, the
HasState capability has the superclasses
HasSource and HasSink and the method
. The corresponding
dictionary type is defined as follows.state :: (s -> (a, s)) -> m a
>>>:{data instance Reified tag (HasState tag s) m = ReifiedState { _stateSource :: Reified tag (HasSource tag s) m, _stateSink :: Reified tag (HasSink tag s) m, _state :: forall a. (s -> (a, s)) -> m a } :}
Instances
| data Reified (tag :: k) (HasSink tag a) m Source # | |
Defined in Capability.Sink.Internal.Class | |
| data Reified (tag :: k) (HasSource tag a) m Source # | |
Defined in Capability.Source.Internal.Class | |
| data Reified (tag :: k) (HasReader tag r) m Source # | |
Defined in Capability.Reader.Internal.Class data Reified (tag :: k) (HasReader tag r) m = ReifiedReader {
| |
| data Reified (tag :: k) (HasState tag s) m Source # | |
Defined in Capability.State.Internal.Class data Reified (tag :: k) (HasState tag s) m = ReifiedState {
| |
| data Reified (tag :: k) (HasThrow tag e) m Source # | |
Defined in Capability.Error | |
| data Reified (tag :: k) (HasCatch tag e) m Source # | |
Defined in Capability.Error data Reified (tag :: k) (HasCatch tag e) m = ReifiedCatch {
| |
| data Reified (tag :: k) (HasWriter tag w) m Source # | |
Defined in Capability.Writer | |
newtype Reflected (s :: Type) (c :: Capability) (m :: Type -> Type) (a :: Type) Source #
Reflected s capability m
Carries the type class instance for capability in the monad m defined by
the dictionary reflected in s in the type system.
For most use-cases it is not necessary to use this type directly. Use
interpret_ or interpret instead.
If you wish to enable reflection for a new capability, then you will need to
define a type class instance for Reflected for the new capability. Note,
you will also need to define an instance of Reified which defines the
dictionary type of the new capability. Hint, you can use to
obtain the dictionary from the context in the instance implementation.reified @s
For example, the Reflected instance for the HasSink
capability can be defined as follows. Assuming the dictionary described in
Reified.
>>>:{instance (Monad m, Reifies s (Reified tag (HasSink tag a) m)) => HasSink tag a (Reflected s (HasSink tag a) m) where yield a = Reflect $ _yield (reified @s) a :}
Constructors
| Reflect (m a) |
Instances
| (Monad m, Reifies s (Reified tag (HasSink tag a) m)) => HasSink (tag :: k) a (Reflected s (HasSink tag a) m) Source # | |
| (Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasSink (tag :: k) s (Reflected s' (HasState tag s) m) Source # | |
| (Monoid w, Monad m, Reifies s (Reified tag (HasWriter tag w) m)) => HasSink (tag :: k) w (Reflected s (HasWriter tag w) m) Source # | |
| (Monad m, Reifies s (Reified tag (HasSource tag a) m)) => HasSource (tag :: k) a (Reflected s (HasSource tag a) m) Source # | |
| (Monad m, Reifies s (Reified tag (HasReader tag r) m)) => HasSource (tag :: k) r (Reflected s (HasReader tag r) m) Source # | |
| (Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasSource (tag :: k) s (Reflected s' (HasState tag s) m) Source # | |
| (Monad m, Reifies s (Reified tag (HasReader tag r) m)) => HasReader (tag :: k) r (Reflected s (HasReader tag r) m) Source # | |
| (Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasState (tag :: k) s (Reflected s' (HasState tag s) m) Source # | |
| (Monad m, Reifies s (Reified tag (HasCatch tag e) m)) => HasCatch (tag :: k) e (Reflected s (HasCatch tag e) m) Source # | |
Defined in Capability.Error Methods catch_ :: Proxy# tag -> Reflected s (HasCatch tag e) m a -> (e -> Reflected s (HasCatch tag e) m a) -> Reflected s (HasCatch tag e) m a Source # catchJust_ :: Proxy# tag -> (e -> Maybe b) -> Reflected s (HasCatch tag e) m a -> (b -> Reflected s (HasCatch tag e) m a) -> Reflected s (HasCatch tag e) m a Source # | |
| (Monad m, Reifies s (Reified tag (HasThrow tag e) m)) => HasThrow (tag :: k) e (Reflected s (HasThrow tag e) m) Source # | |
| (Monad m, Reifies s (Reified tag (HasCatch tag e) m)) => HasThrow (tag :: k) e (Reflected s (HasCatch tag e) m) Source # | |
| (Monad m, Monoid w, Reifies s (Reified tag (HasWriter tag w) m)) => HasWriter (tag :: k) w (Reflected s (HasWriter tag w) m) Source # | |
Defined in Capability.Writer Methods writer_ :: Proxy# tag -> (a, w) -> Reflected s (HasWriter tag w) m a Source # listen_ :: Proxy# tag -> Reflected s (HasWriter tag w) m a -> Reflected s (HasWriter tag w) m (a, w) Source # pass_ :: Proxy# tag -> Reflected s (HasWriter tag w) m (a, w -> w) -> Reflected s (HasWriter tag w) m a Source # | |
| Monad m => Monad (Reflected s c m) Source # | |
| Functor m => Functor (Reflected s c m) Source # | |
| Applicative m => Applicative (Reflected s c m) Source # | |
Defined in Capability.Reflection Methods pure :: a -> Reflected s c m a # (<*>) :: Reflected s c m (a -> b) -> Reflected s c m a -> Reflected s c m b # liftA2 :: (a -> b -> c0) -> Reflected s c m a -> Reflected s c m b -> Reflected s c m c0 # (*>) :: Reflected s c m a -> Reflected s c m b -> Reflected s c m b # (<*) :: Reflected s c m a -> Reflected s c m b -> Reflected s c m a # | |
reified :: forall s tag c m. Reifies s (Reified tag c m) => Reified tag c m Source #
reified @s
Obtain the dictionary that is reflected in the type system under s.
This is a convenience wrapper around reflect.
Re-exported
class Reifies (s :: k) a | s -> a #
Minimal complete definition
Instances
| KnownNat n => Reifies (n :: Nat) Integer | |
Defined in Data.Reflection | |
| KnownSymbol n => Reifies (n :: Symbol) String | |
Defined in Data.Reflection | |
| Reifies Z Int | |
Defined in Data.Reflection | |
| Reifies n Int => Reifies (D n :: Type) Int | |
Defined in Data.Reflection | |
| Reifies n Int => Reifies (SD n :: Type) Int | |
Defined in Data.Reflection | |
| Reifies n Int => Reifies (PD n :: Type) Int | |
Defined in Data.Reflection | |
| (B b0, B b1, B b2, B b3, B b4, B b5, B b6, B b7, w0 ~ W b0 b1 b2 b3, w1 ~ W b4 b5 b6 b7) => Reifies (Stable w0 w1 a :: Type) a | |
Defined in Data.Reflection | |
reify :: a -> (forall s. Reifies s a => Proxy s -> r) -> r #
Reify a value at the type level, to be recovered with reflect.
reflect :: Reifies s a => proxy s -> a #
Recover a value inside a reify context, given a proxy for its
reified type.
Proxy is a type that holds no data, but has a phantom parameter of
arbitrary type (or even kind). Its use is to provide type information, even
though there is no value available of that type (or it may be too costly to
create one).
Historically, is a safer alternative to the
Proxy :: Proxy a idiom.undefined :: a
>>>Proxy :: Proxy (Void, Int -> Int)Proxy
Proxy can even hold types of higher kinds,
>>>Proxy :: Proxy EitherProxy
>>>Proxy :: Proxy FunctorProxy
>>>Proxy :: Proxy complicatedStructureProxy
Constructors
| Proxy |
Instances
| Generic1 (Proxy :: k -> Type) | Since: base-4.6.0.0 |
| Monad (Proxy :: Type -> Type) | Since: base-4.7.0.0 |
| Functor (Proxy :: Type -> Type) | Since: base-4.7.0.0 |
| Applicative (Proxy :: Type -> Type) | Since: base-4.7.0.0 |
| Foldable (Proxy :: Type -> Type) | Since: base-4.7.0.0 |
Defined in Data.Foldable Methods fold :: Monoid m => Proxy m -> m # foldMap :: Monoid m => (a -> m) -> Proxy a -> m # foldMap' :: Monoid m => (a -> m) -> Proxy a -> m # foldr :: (a -> b -> b) -> b -> Proxy a -> b # foldr' :: (a -> b -> b) -> b -> Proxy a -> b # foldl :: (b -> a -> b) -> b -> Proxy a -> b # foldl' :: (b -> a -> b) -> b -> Proxy a -> b # foldr1 :: (a -> a -> a) -> Proxy a -> a # foldl1 :: (a -> a -> a) -> Proxy a -> a # elem :: Eq a => a -> Proxy a -> Bool # maximum :: Ord a => Proxy a -> a # minimum :: Ord a => Proxy a -> a # | |
| Traversable (Proxy :: Type -> Type) | Since: base-4.7.0.0 |
| Representable (Proxy :: Type -> Type) | |
| Eq1 (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
| Ord1 (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
Defined in Data.Functor.Classes | |
| Read1 (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
Defined in Data.Functor.Classes | |
| Show1 (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
| Alternative (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
| MonadPlus (Proxy :: Type -> Type) | Since: base-4.9.0.0 |
| Hashable1 (Proxy :: Type -> Type) | |
Defined in Data.Hashable.Class | |
| Bounded (Proxy t) | Since: base-4.7.0.0 |
| Enum (Proxy s) | Since: base-4.7.0.0 |
| Eq (Proxy s) | Since: base-4.7.0.0 |
| Ord (Proxy s) | Since: base-4.7.0.0 |
| Read (Proxy t) | Since: base-4.7.0.0 |
| Show (Proxy s) | Since: base-4.7.0.0 |
| Ix (Proxy s) | Since: base-4.7.0.0 |
Defined in Data.Proxy | |
| Generic (Proxy t) | Since: base-4.6.0.0 |
| Semigroup (Proxy s) | Since: base-4.9.0.0 |
| Monoid (Proxy s) | Since: base-4.7.0.0 |
| Hashable (Proxy a) | |
Defined in Data.Hashable.Class | |
| MonoFunctor (Proxy a) | Since: mono-traversable-1.0.11.0 |
| MonoFoldable (Proxy a) | Since: mono-traversable-1.0.11.0 |
Defined in Data.MonoTraversable Methods ofoldMap :: Monoid m => (Element (Proxy a) -> m) -> Proxy a -> m # ofoldr :: (Element (Proxy a) -> b -> b) -> b -> Proxy a -> b # ofoldl' :: (a0 -> Element (Proxy a) -> a0) -> a0 -> Proxy a -> a0 # otoList :: Proxy a -> [Element (Proxy a)] # oall :: (Element (Proxy a) -> Bool) -> Proxy a -> Bool # oany :: (Element (Proxy a) -> Bool) -> Proxy a -> Bool # olength64 :: Proxy a -> Int64 # ocompareLength :: Integral i => Proxy a -> i -> Ordering # otraverse_ :: Applicative f => (Element (Proxy a) -> f b) -> Proxy a -> f () # ofor_ :: Applicative f => Proxy a -> (Element (Proxy a) -> f b) -> f () # omapM_ :: Applicative m => (Element (Proxy a) -> m ()) -> Proxy a -> m () # oforM_ :: Applicative m => Proxy a -> (Element (Proxy a) -> m ()) -> m () # ofoldlM :: Monad m => (a0 -> Element (Proxy a) -> m a0) -> a0 -> Proxy a -> m a0 # ofoldMap1Ex :: Semigroup m => (Element (Proxy a) -> m) -> Proxy a -> m # ofoldr1Ex :: (Element (Proxy a) -> Element (Proxy a) -> Element (Proxy a)) -> Proxy a -> Element (Proxy a) # ofoldl1Ex' :: (Element (Proxy a) -> Element (Proxy a) -> Element (Proxy a)) -> Proxy a -> Element (Proxy a) # headEx :: Proxy a -> Element (Proxy a) # lastEx :: Proxy a -> Element (Proxy a) # unsafeHead :: Proxy a -> Element (Proxy a) # unsafeLast :: Proxy a -> Element (Proxy a) # maximumByEx :: (Element (Proxy a) -> Element (Proxy a) -> Ordering) -> Proxy a -> Element (Proxy a) # minimumByEx :: (Element (Proxy a) -> Element (Proxy a) -> Ordering) -> Proxy a -> Element (Proxy a) # | |
| MonoTraversable (Proxy a) | Since: mono-traversable-1.0.11.0 |
| MonoPointed (Proxy a) | Since: mono-traversable-1.0.11.0 |
| type Rep1 (Proxy :: k -> Type) | |
| type Rep (Proxy :: Type -> Type) | |
| type Rep (Proxy t) | |
| type Element (Proxy a) | |
Defined in Data.MonoTraversable | |