packages feed

data-effects-core 0.4.1.0 → 0.4.2.0

raw patch · 5 files changed

+142/−12 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Control.Effect.Transform: onlyPolys :: forall (es :: [Effect]) a (ff :: (Type -> Type) -> Type -> Type) (c :: (Type -> Type) -> Constraint). (Free c ff, WeakenExps es) => Eff ff (RemoveExps es) a -> Eff ff es a
+ Data.Effect: Exponential :: EffectForm
+ Data.Effect: Polynomial :: EffectForm
+ Data.Effect: data EffectForm
+ Data.Effect: instance GHC.Classes.Eq Data.Effect.EffectForm
+ Data.Effect: instance GHC.Classes.Ord Data.Effect.EffectForm
+ Data.Effect: instance GHC.Show.Show Data.Effect.EffectForm
+ Data.Effect.OpenUnion: (!:>) :: forall (e :: Effect) (e' :: Effect) (es :: [Effect]) r. ((e :~: e') -> r) -> (Membership e es -> r) -> Membership e (e' ': es) -> r
+ Data.Effect.OpenUnion: class formOfHead ~ FormOf HeadOf es => WeakenExps_ (es :: [Effect]) (countP :: Natural) (formOfHead :: EffectForm)
+ Data.Effect.OpenUnion: foldExpIndexShifter :: WeakenExps_ es countP formOfHead => (Int -> Int) -> Int -> Int
+ Data.Effect.OpenUnion: instance (Data.Effect.FormOf (Data.Effect.OpenUnion.HeadOf '[]) GHC.Types.~ formOfHead) => Data.Effect.OpenUnion.WeakenExps_ '[] countP formOfHead
+ Data.Effect.OpenUnion: instance (Data.Effect.FormOf e GHC.Types.~ 'Data.Effect.Exponential, Data.Effect.OpenUnion.WeakenExps_ es countP _formOfHead, GHC.TypeNats.KnownNat countP) => Data.Effect.OpenUnion.WeakenExps_ (e : es) countP 'Data.Effect.Exponential
+ Data.Effect.OpenUnion: instance (Data.Effect.PolyHFunctor e, Data.Effect.OpenUnion.WeakenExps_ es (countP GHC.TypeNats.+ 1) _formOfHead) => Data.Effect.OpenUnion.WeakenExps_ (e : es) countP 'Data.Effect.Polynomial
+ Data.Effect.OpenUnion: mergeUnion1 :: forall {k} (fs :: [k -> Effect]) (x :: k) (es :: [Effect]) (f :: Type -> Type) a. KnownLength fs => Either (Union (Each fs x) f a) (Union es f a) -> Union (Each fs x ++ es) f a
+ Data.Effect.OpenUnion: splitFor1 :: forall {k} (fs :: [k -> Effect]) (x :: k) (es :: [Effect]) (e :: Effect) r. KnownLength fs => (Membership e (Each fs x) -> r) -> (Membership e es -> r) -> Membership e (Each fs x ++ es) -> r
+ Data.Effect.OpenUnion: splitUnion1 :: forall {k} (fs :: [k -> Effect]) (x :: k) (es :: [Effect]) (es' :: [Effect]) (f :: Type -> Type) a. KnownLength fs => (forall (e :: Effect). () => Membership e (Each fs x) -> Membership e es') -> (forall (e :: Effect). () => Membership e es -> Membership e es') -> Union (Each fs x ++ es) f a -> Union es' f a
+ Data.Effect.OpenUnion: type WeakenExps (es :: [Effect]) = (WeakenExps_ es 0 FormOf HeadOf es, PolyHFunctors RemoveExps es)
+ Data.Effect.OpenUnion: weakenExps :: forall (es :: [Effect]) (f :: Type -> Type) a. WeakenExps es => Union (RemoveExps es) f a -> Union es f a
+ Data.Effect.OpenUnion: weakenExpsFor :: forall (es :: [Effect]) (e :: Effect). WeakenExps es => Membership e (RemoveExps es) -> Membership e es
- Data.Effect: class PolyHFunctor (e :: Effect)
+ Data.Effect: class FormOf e ~ 'Polynomial => PolyHFunctor (e :: Effect)
- Data.Effect.OpenUnion: class FOEs (es :: k)
+ Data.Effect.OpenUnion: class FOEs (es :: [Effect])
- Data.Effect.OpenUnion: class PolyHFunctors (es :: k)
+ Data.Effect.OpenUnion: class PolyHFunctors (es :: [Effect])

Files

data-effects-core.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               data-effects-core-version:            0.4.1.0+version:            0.4.2.0  -- A short (one-line) description of the package. synopsis: A basic framework for effect systems based on effects represented by GADTs.@@ -37,7 +37,7 @@ source-repository head     type: git     location: https://github.com/sayo-hs/data-effects-    tag: v0.4.1.0+    tag: v0.4.2.0     subdir: data-effects-core  library
src/Control/Effect/Transform.hs view
@@ -19,10 +19,12 @@     KnownLength,     KnownOrder,     Membership,+    RemoveExps,     RemoveHOEs,     Suffix,     SuffixUnder,     Union,+    WeakenExps,     WeakenHOEs,     hfmapUnion,     identityMembership,@@ -34,6 +36,7 @@     prefixFor1,     suffixFor,     weaken,+    weakenExps,     weakenFor,     weakenHOEs,     weakens,@@ -68,6 +71,10 @@ onlyFOEs :: forall es a ff c. (Free c ff, WeakenHOEs es) => Eff ff (RemoveHOEs es) a -> Eff ff es a onlyFOEs = transAll weakenHOEs {-# INLINE onlyFOEs #-}++onlyPolys :: forall es a ff c. (Free c ff, WeakenExps es) => Eff ff (RemoveExps es) a -> Eff ff es a+onlyPolys = transAll weakenExps+{-# INLINE onlyPolys #-}  raisePrefix     :: forall es' es a ff c
src/Data/Effect.hs view
@@ -23,10 +23,19 @@  type family OrderOf (e :: Effect) :: EffectOrder -type family OrderCase (e :: EffectOrder) a b where+type family OrderCase (o :: EffectOrder) a b where     OrderCase 'FirstOrder a b = a     OrderCase 'HigherOrder a b = b +data EffectForm = Polynomial | Exponential+    deriving (Show, Eq, Ord)++type family FormOf (e :: Effect) :: EffectForm++type family FormCase (f :: EffectForm) a b where+    FormCase 'Polynomial a b = a+    FormCase 'Exponential a b = b+ type family LabelOf (e :: Effect)  class@@ -36,7 +45,7 @@     FirstOrder (e :: Effect)  -- | A higher-order polynomial functor.-class PolyHFunctor (e :: Effect)+class (FormOf e ~ 'Polynomial) => PolyHFunctor (e :: Effect)  -- * Nop Effect @@ -50,6 +59,7 @@ instance HFunctor Nop where     hfmap _ = \case {}     {-# INLINE hfmap #-}+type instance FormOf Nop = 'Polynomial instance PolyHFunctor Nop  -- * Embedding Effect@@ -65,6 +75,7 @@ instance HFunctor (Emb e) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (Emb e) = 'Polynomial instance PolyHFunctor (Emb e)  newtype Unemb e a = Unemb {getUnemb :: forall f. e f a}@@ -83,6 +94,7 @@ instance HFunctor (Ask r) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (Ask r) = 'Polynomial instance PolyHFunctor (Ask r)  -- | An effect that locally modifies the value held in the environment.@@ -101,6 +113,7 @@ instance HFunctor (Local r) where     hfmap phi (Local f a) = Local f (phi a)     {-# INLINE hfmap #-}+type instance FormOf (Local r) = 'Polynomial instance PolyHFunctor (Local r)  -- * State Effect@@ -119,6 +132,7 @@ instance HFunctor (State s) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (State s) = 'Polynomial instance PolyHFunctor (State s)  -- * Writer Effects@@ -135,6 +149,7 @@ instance HFunctor (Tell w) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (Tell w) = 'Polynomial instance PolyHFunctor (Tell w)  -- | An effect that performs local operations on accumulations in the context on a per-scope basis.@@ -160,6 +175,7 @@         Listen a -> Listen $ phi a         Censor f a -> Censor f (phi a)     {-# INLINE hfmap #-}+type instance FormOf (WriterH w) = 'Polynomial instance PolyHFunctor (WriterH w)  -- * Exception Effects@@ -176,6 +192,7 @@ instance HFunctor (Throw e) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (Throw e) = 'Polynomial instance PolyHFunctor (Throw e)  -- | An effect to catch exceptions.@@ -194,6 +211,7 @@ instance HFunctor (Catch e) where     hfmap phi (Catch a hdl) = Catch (phi a) (phi . hdl)     {-# INLINE hfmap #-}+type instance FormOf (Catch e) = 'Polynomial instance PolyHFunctor (Catch e)  -- * Non-Determinism Effects@@ -210,6 +228,7 @@ instance HFunctor Empty where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf Empty = 'Polynomial instance PolyHFunctor Empty  -- | An effect that splits the computation into two branches.@@ -225,6 +244,7 @@ instance HFunctor Choose where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf Choose = 'Polynomial instance PolyHFunctor Choose  {- |@@ -242,6 +262,7 @@ instance HFunctor ChooseH where     hfmap phi (ChooseH a b) = ChooseH (phi a) (phi b)     {-# INLINE hfmap #-}+type instance FormOf ChooseH = 'Polynomial instance PolyHFunctor ChooseH  -- * Fail Effect@@ -256,6 +277,7 @@ instance HFunctor Fail where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf Fail = 'Polynomial instance PolyHFunctor Fail  -- * Fix Effect@@ -269,6 +291,7 @@ instance HFunctor Fix where     hfmap phi (Efix f) = Efix $ phi . f     {-# INLINE hfmap #-}+type instance FormOf Fix = 'Polynomial instance PolyHFunctor Fix  -- * Unlift Effect@@ -284,8 +307,7 @@ instance HFunctor (UnliftBase b) where     hfmap phi (WithRunInBase f) = WithRunInBase \run -> f $ run . phi     {-# INLINE hfmap #-}---- The Unlift effect is not polynomial.+type instance FormOf (UnliftBase b) = 'Exponential  -- * CallCC Effect (Sub/Jump-based) @@ -300,4 +322,5 @@ instance HFunctor (CC ref) where     hfmap _ = coerce     {-# INLINE hfmap #-}+type instance FormOf (CC ref) = 'Polynomial instance PolyHFunctor (CC ref)
src/Data/Effect/OpenUnion.hs view
@@ -16,7 +16,7 @@ import Control.Arrow ((&&&)) import Data.Coerce (coerce) import Data.Data (Proxy (Proxy), (:~:) (Refl))-import Data.Effect (Effect, EffectOrder (FirstOrder, HigherOrder), FirstOrder, LabelOf, OrderCase, OrderOf, PolyHFunctor)+import Data.Effect (Effect, EffectForm (Exponential, Polynomial), EffectOrder (FirstOrder, HigherOrder), FirstOrder, FormCase, FormOf, LabelOf, OrderCase, OrderOf, PolyHFunctor) import Data.Effect.HFunctor (HFunctor, hfmap) import Data.Effect.Tag (type (#)) import Data.Kind (Constraint, Type)@@ -47,13 +47,13 @@ {-# INLINE hfmapUnion #-}  -- | The list @es@ consists only of first-order effects.-class FOEs es+class FOEs (es :: [Effect])  instance FOEs '[] instance (FirstOrder e, FOEs es) => FOEs (e ': es)  -- | The list @es@ consists only of polynomial effects.-class PolyHFunctors es+class PolyHFunctors (es :: [Effect])  instance PolyHFunctors '[] instance (PolyHFunctor e, PolyHFunctors es) => PolyHFunctors (e ': es)@@ -77,7 +77,12 @@         There (UnsafeMembership n) = UnsafeMembership (n + 1) {-# INLINE There #-} -{-# COMPLETE Here, There #-}+infixr 5 !:>+(!:>) :: forall e e' es r. ((e :~: e') -> r) -> (Membership e es -> r) -> Membership e (e' ': es) -> r+(f !:> g) (UnsafeMembership n)+    | n == 0 = f $ unsafeCoerce Refl+    | otherwise = g $ UnsafeMembership $ n - 1+{-# INLINE (!:>) #-}  weakenFor :: Membership e es -> Membership e (e' ': es) weakenFor (UnsafeMembership n) = UnsafeMembership $ n + 1@@ -428,6 +433,36 @@                     else shiftedIx + 1     {-# INLINE foldHoeIndexShifter #-} +type family RemoveExps (es :: [Effect]) where+    RemoveExps '[] = '[]+    RemoveExps (e ': es) =+        FormCase (FormOf e) (e ': RemoveExps es) (RemoveExps es)++type WeakenExps es = (WeakenExps_ es 0 (FormOf (HeadOf es)), PolyHFunctors (RemoveExps es))++class (formOfHead ~ FormOf (HeadOf es)) => WeakenExps_ es (countP :: Natural) formOfHead where+    foldExpIndexShifter :: (Int -> Int) -> (Int -> Int)++instance (FormOf (HeadOf '[]) ~ formOfHead) => WeakenExps_ '[] countP formOfHead where+    foldExpIndexShifter = id+    {-# INLINE foldExpIndexShifter #-}++instance (PolyHFunctor e, WeakenExps_ es (countP + 1) _formOfHead) => WeakenExps_ (e ': es) countP 'Polynomial where+    foldExpIndexShifter = foldExpIndexShifter @es @(countP + 1)+    {-# INLINE foldExpIndexShifter #-}++instance+    (FormOf e ~ 'Exponential, WeakenExps_ es countP _formOfHead, KnownNat countP)+    => WeakenExps_ (e ': es) countP 'Exponential+    where+    foldExpIndexShifter shifterAcc =+        foldExpIndexShifter @es @countP \ix ->+            let shiftedIx = shifterAcc ix+             in if ix < intVal @countP+                    then shiftedIx+                    else shiftedIx + 1+    {-# INLINE foldExpIndexShifter #-}+ weaken :: Union es f a -> Union (e ': es) f a weaken = mapUnion weakenFor {-# INLINE weaken #-}@@ -448,6 +483,14 @@ weakenHOEs = mapUnion weakenHOEsFor {-# INLINE weakenHOEs #-} +weakenExpsFor :: forall es e. (WeakenExps es) => Membership e (RemoveExps es) -> Membership e es+weakenExpsFor = UnsafeMembership . foldExpIndexShifter @es @0 id . unMembership+{-# INLINE weakenExpsFor #-}++weakenExps :: forall es f a. (WeakenExps es) => Union (RemoveExps es) f a -> Union es f a+weakenExps = mapUnion weakenExpsFor+{-# INLINE weakenExps #-}+ type KnownLength :: forall {k}. [k] -> Constraint class KnownLength xs where     reifyLength :: Int@@ -515,6 +558,26 @@     Right u -> mapUnion (prefixFor @es) u {-# INLINE mergeUnion #-} +splitUnion1+    :: forall fs x es es' f a+     . (KnownLength fs)+    => (forall e. Membership e (Each fs x) -> Membership e es')+    -> (forall e. Membership e es -> Membership e es')+    -> Union (Each fs x ++ es) f a+    -> Union es' f a+splitUnion1 injL injR = mapUnion $ splitFor1 @fs @x @es injL injR+{-# INLINE splitUnion1 #-}++mergeUnion1+    :: forall fs x es f a+     . (KnownLength fs)+    => Either (Union (Each fs x) f a) (Union es f a)+    -> Union (Each fs x ++ es) f a+mergeUnion1 = \case+    Left u -> mapUnion (suffixFor @es) u+    Right u -> mapUnion (prefixFor1 @fs @x) u+{-# INLINE mergeUnion1 #-}+ splitFor     :: forall es es' e r      . (KnownLength es)@@ -528,6 +591,20 @@   where     l = reifyLength @es {-# INLINE splitFor #-}++splitFor1+    :: forall fs x es e r+     . (KnownLength fs)+    => (Membership e (Each fs x) -> r)+    -> (Membership e es -> r)+    -> Membership e (Each fs x ++ es)+    -> r+splitFor1 f g (UnsafeMembership n)+    | n < l = f $ UnsafeMembership n+    | otherwise = g $ UnsafeMembership $ n - l+  where+    l = reifyLength @fs+{-# INLINE splitFor1 #-}  suffixFor :: forall es' es e. Membership e es -> Membership e (es ++ es') suffixFor = coerce
test/OpenUnion.hs view
@@ -8,8 +8,8 @@ module OpenUnion where  import Control.Effect (Eff, Free, perform)-import Data.Effect (Catch, Effect, LabelOf, Throw (Throw))-import Data.Effect.OpenUnion (Membership (UnsafeMembership), labelMembership, membershipAt, weakenHOEsFor, (:>))+import Data.Effect (Catch, Effect, LabelOf, Throw (Throw), UnliftIO)+import Data.Effect.OpenUnion (Membership (UnsafeMembership), labelMembership, membershipAt, weakenExpsFor, weakenHOEsFor, (:>)) import Data.Proxy (Proxy (Proxy)) import GHC.TypeNats (KnownNat, Natural, natVal) import Test.Hspec (Spec, describe, it, shouldBe)@@ -60,6 +60,29 @@     shiftIx = weakenHOEsFor      ix0, ix1, ix2, ix3 :: Membership F '[F, F, F, F]+    ix0 = membershipAt @0+    ix1 = membershipAt @1+    ix2 = membershipAt @2+    ix3 = membershipAt @3++type P = Catch ()+type E = UnliftIO++spec_onlyPolys :: Spec+spec_onlyPolys = describe "onlyPolys index shift" do+    it "'[<P>, P , P , P ] -> '[ E ,<P>, P , E , E , P , E , P ]" $+        shiftIx ix0 `shouldBe` UnsafeMembership 1+    it "'[ P ,<P>, P , P ] -> '[ E , P ,<P>, E , E , P , E , P ]" $+        shiftIx ix1 `shouldBe` UnsafeMembership 2+    it "'[ P , P ,<P>, P ] -> '[ E , P , P , E , E ,<P>, E , P ]" $+        shiftIx ix2 `shouldBe` UnsafeMembership 5+    it "'[ P , P , P ,<P>] -> '[ E , P , P , E , E , P , E ,<P>]" $+        shiftIx ix3 `shouldBe` UnsafeMembership 7+  where+    shiftIx :: Membership e '[P, P, P, P] -> Membership e '[E, P, P, E, E, P, E, P]+    shiftIx = weakenExpsFor++    ix0, ix1, ix2, ix3 :: Membership P '[P, P, P, P]     ix0 = membershipAt @0     ix1 = membershipAt @1     ix2 = membershipAt @2