packages feed

classy-effects-0.1.0.0: src/Control/Effect/Class/Provider.hs

{-# LANGUAGE UndecidableInstances #-}

-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.

{- |
Copyright   :  (c) 2023 Yamada Ryo
License     :  MPL-2.0 (see the file LICENSE)
Maintainer  :  ymdfield@outlook.jp
Stability   :  experimental
Portability :  portable

This module provides the `Provider` effect, comes
from [@Effectful.Provider@](https://hackage.haskell.org/package/effectful-core-2.3.0.0/docs/Effectful-Provider.html)
in the @effectful@ package.
-}
module Control.Effect.Class.Provider where

import Control.Effect.Class (
    EffectDataHandler,
    EffectsVia (EffectsVia),
    SendSig,
    runEffectsVia,
    sendSig,
    type (~>),
 )
import Control.Effect.Class.Machinery.HFunctor (HFunctor, hfmap)
import Data.Effect.Class.TH (
    makeSignature,
 )

class Provider c e i g (f :: Type -> Type) where
    provide :: i -> (forall h. (c h, e h) => (f ~> h) -> h a) -> f (g a)

makeSignature ''Provider

instance HFunctor (ProviderS c e i g) where
    hfmap phi (Provide i f) = Provide i \l -> f $ l . phi

instance
    SendSig (ProviderS c e i g) f =>
    Provider c e i g (EffectsVia EffectDataHandler f)
    where
    {-# INLINE provide #-}
    provide i f =
        EffectsVia
            . sendSig
            . hfmap (runEffectsVia @EffectDataHandler)
            $ Provide @c @e i f

type MonadProvider = Provider Monad
type ApplicativeProvider = Provider Applicative

mprovide ::
    MonadProvider e i g f =>
    i ->
    (forall h. (Monad h, e h) => (f ~> h) -> h a) ->
    f (g a)
mprovide = provide
{-# INLINE mprovide #-}

aprovide ::
    ApplicativeProvider e i g f =>
    i ->
    (forall h. (Applicative h, e h) => (f ~> h) -> h a) ->
    f (g a)
aprovide = provide
{-# INLINE aprovide #-}