content: -- | Defines a capability for computations that consume a stream of values
  -- as part of their execution.
  --
  -- Programs comsuming streams of data are common. Examples: rolling up input
  -- events. Sources are similar to Python generators.
  --
  -- This can be thought of as a reader capability where there's no guarantee that
  -- one reads the same value each time.
  --
  -- The 'HasSource' capability enables separating the logic responsible for
  -- emitting events from that responsible for collecting or handling them.
  -- The name is because a source is needed to produce the locally consumed stream.
  --
  
  {-# LANGUAGE AllowAmbiguousTypes #-}
  {-# LANGUAGE ConstraintKinds #-}
  {-# LANGUAGE DerivingVia #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  {-# LANGUAGE KindSignatures #-}
  {-# LANGUAGE MagicHash #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE QuantifiedConstraints #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE StandaloneDeriving #-}
  {-# LANGUAGE TypeApplications #-}
  {-# LANGUAGE TypeInType #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE UnboxedTuples #-}
  {-# LANGUAGE UndecidableInstances #-}
  
  {-# OPTIONS_HADDOCK hide #-}
  
  module Capability.Source.Internal.Class where
  
  import Capability.Reflection
  import Data.Coerce (coerce)
  import Data.Kind (Type)
  import GHC.Exts (Proxy#, proxy#)
  
  -- | Sourcing capability.
  --
  -- An instance does not need to fulfill any additional laws
  -- besides the monad laws.
  class Monad m
    => HasSource (tag :: k) (a :: Type) (m :: Type -> Type) | tag m -> a
    where
      -- | For technical reasons, this method needs an extra proxy argument.
      -- You only need it if you are defining new instances of 'HasSource'.
      -- Otherwise, you will want to use 'await'.
      -- See 'await' for more documentation.
      await_ :: Proxy# tag -> m a
  
  -- | @await \@tag a@
  -- takes @a@ from the source capability @tag@.
  await :: forall tag a m. HasSource tag a m => m a
  await = await_ (proxy# @tag)
  {-# INLINE await #-}
  
  -- | @awaits \@tag@
  -- retrieves the image by @f@ of the environment
  -- of the source capability @tag@.
  --
  -- prop> awaits @tag f = f <$> await @tag
  awaits :: forall tag r m a. HasSource tag r m => (r -> a) -> m a
  awaits f = f <$> await @tag
  {-# INLINE awaits #-}
  
  --------------------------------------------------------------------------------
  
  data instance Reified tag (HasSource tag a) m = ReifiedSource {_await :: m a}
  
  instance
    ( Monad m,
      Reifies s (Reified tag (HasSource tag a) m)
    ) =>
    HasSource tag a (Reflected s (HasSource tag a) m)
    where
    await_ _ = coerce $ _await (reified @s)
    {-# INLINE await_ #-}
  