Safe Haskell | None |
---|---|
Language | Haskell2010 |
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 :}
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 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 | |
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 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 #
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 Either
Proxy
>>>
Proxy :: Proxy Functor
Proxy
>>>
Proxy :: Proxy complicatedStructure
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 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 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 |