Skip to content

Commit f74ec79

Browse files
authored
Merge pull request #6 from antitypical/distributive-algebra
🔥 dependency on fused-effects
2 parents d11e145 + 1c99dc1 commit f74ec79

File tree

10 files changed

+139
-27
lines changed

10 files changed

+139
-27
lines changed

fused-syntax.cabal

+6-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,16 @@ common common
3232
-Wno-unsafe
3333
if (impl(ghc >= 8.8))
3434
ghc-options: -Wno-missing-deriving-strategies
35+
if (impl(ghc >= 8.10))
36+
ghc-options:
37+
-Wno-missing-safe-haskell-mode
38+
-Wno-prepositive-qualified-module
3539

3640
library
3741
import: common
3842
hs-source-dirs: src
3943
exposed-modules:
44+
Syntax.Algebra
4045
Syntax.Fin
4146
Syntax.Fix
4247
Syntax.Foldable
@@ -55,6 +60,5 @@ library
5560
other-modules:
5661
Example.Lam
5762
build-depends:
58-
base >= 4.12 && < 4.14
59-
, fused-effects ^>= 1
63+
base >= 4.12 && < 5
6064
, transformers ^>= 0.5.6

src/Example/Lam.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
{-# LANGUAGE ConstraintKinds, DeriveGeneric, DeriveTraversable, FlexibleContexts, LambdaCase, MultiParamTypeClasses, QuantifiedConstraints, StandaloneDeriving, TypeFamilies #-}
1+
{-# LANGUAGE ConstraintKinds, DeriveGeneric, DeriveTraversable, FlexibleContexts, MultiParamTypeClasses, QuantifiedConstraints, StandaloneDeriving, TypeFamilies #-}
22
module Example.Lam
33
( Lam(..)
44
, lam
55
, ($$)
66
) where
77

8-
import Control.Algebra
98
import GHC.Generics (Generic1)
9+
import Syntax.Algebra
1010
import Syntax.Foldable
11+
import Syntax.Functor
1112
import Syntax.Module
1213
import Syntax.Scope
1314
import Syntax.Traversable

src/Syntax/Algebra.hs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{-# LANGUAGE ConstraintKinds #-}
2+
{-# LANGUAGE FunctionalDependencies #-}
3+
module Syntax.Algebra
4+
( Algebra(..)
5+
, Has
6+
, send
7+
) where
8+
9+
import Syntax.Functor
10+
import Syntax.Sum
11+
12+
class (HFunctor sig, Applicative t) => Algebra sig t | t -> sig where
13+
alg :: sig t a -> t a
14+
15+
16+
-- | @m@ is a carrier for @sig@ containing @eff@.
17+
--
18+
-- Note that if @eff@ is a sum, it will be decomposed into multiple 'Member' constraints. While this technically allows one to combine multiple unrelated effects into a single 'Has' constraint, doing so has two significant drawbacks:
19+
--
20+
-- 1. Due to [a problem with recursive type families](https://gitlab.haskell.org/ghc/ghc/issues/8095), this can lead to significantly slower compiles.
21+
--
22+
-- 2. It defeats @ghc@’s warnings for redundant constraints, and thus can lead to a proliferation of redundant constraints as code is changed.
23+
type Has eff sig m = (Members eff sig, Algebra sig m)
24+
25+
-- | Construct a request for an effect to be interpreted by some handler later on.
26+
send :: (Member eff sig, Algebra sig m) => eff m a -> m a
27+
send = alg . inj
28+
{-# INLINE send #-}

src/Syntax/Fix.hs

+2-6
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ deriving instance (forall g . Foldable g => Foldable (sig g)
2525

2626

2727
hoistFix
28-
:: ( HFunctor sig
29-
, forall g . Functor g => Functor (sig g)
30-
)
28+
:: HFunctor sig
3129
=> (forall m x . sig m x -> sig' m x)
3230
-> (Fix sig a -> Fix sig' a)
3331
hoistFix f = cata (Fix . f)
@@ -39,9 +37,7 @@ prjFix = maybe empty pure . prj . unFix
3937

4038
cata
4139
:: forall sig m a
42-
. ( HFunctor sig
43-
, forall g . Functor g => Functor (sig g)
44-
)
40+
. HFunctor sig
4541
=> (forall x . sig m x -> m x)
4642
-> Fix sig a
4743
-> m a

src/Syntax/Functor.hs

+62-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,66 @@
1-
{-# LANGUAGE DefaultSignatures, QuantifiedConstraints, RankNTypes, TypeOperators #-}
1+
{-# LANGUAGE DefaultSignatures #-}
2+
{-# LANGUAGE FlexibleContexts #-}
3+
{-# LANGUAGE FlexibleInstances #-}
4+
{-# LANGUAGE EmptyCase #-}
5+
{-# LANGUAGE LambdaCase #-}
6+
{-# LANGUAGE MultiParamTypeClasses #-}
7+
{-# LANGUAGE QuantifiedConstraints #-}
8+
{-# LANGUAGE RankNTypes #-}
9+
{-# LANGUAGE TypeOperators #-}
210
module Syntax.Functor
311
( HFunctor(..)
12+
, GHFunctor
413
) where
514

6-
import Control.Effect.Class (HFunctor(..))
15+
import qualified Syntax.Sum as Sum
16+
import GHC.Generics
17+
18+
class (forall f . Functor f => Functor (h f)) => HFunctor h where
19+
hmap :: Functor f => (forall x . f x -> g x) -> (h f a -> h g a)
20+
default hmap
21+
:: (Functor f, Generic1 (h f), Generic1 (h g), GHFunctor f g (Rep1 (h f)) (Rep1 (h g)))
22+
=> (forall a . f a -> g a)
23+
-> (h f a -> h g a)
24+
hmap f = to1 . ghmap f . from1
25+
26+
instance (HFunctor l, HFunctor r) => HFunctor (l Sum.:+: r) where
27+
hmap f = \case
28+
Sum.L l -> Sum.L (hmap f l)
29+
Sum.R r -> Sum.R (hmap f r)
30+
{-# INLINE hmap #-}
31+
32+
33+
class GHFunctor g g' rep rep' where
34+
ghmap :: Functor g => (forall x . g x -> g' x) -> rep a -> rep' a
35+
36+
instance GHFunctor g g' V1 V1 where
37+
ghmap _ = \case {}
38+
39+
instance GHFunctor g g' U1 U1 where
40+
ghmap _ = id
41+
42+
instance GHFunctor g g' (K1 R r) (K1 R r) where
43+
ghmap _ = id
44+
45+
instance GHFunctor g g' Par1 Par1 where
46+
ghmap _ = id
47+
48+
instance (GHFunctor g g' l l', GHFunctor g g' r r') => GHFunctor g g' (l :*: r) (l' :*: r') where
49+
ghmap f (l :*: r) = ghmap f l :*: ghmap f r
50+
51+
instance (Traversable f, GHFunctor g g' sig sig') => GHFunctor g g' (f :.: sig) (f :.: sig') where
52+
ghmap f = Comp1 . fmap (ghmap f) . unComp1
53+
54+
instance (GHFunctor g g' l l', GHFunctor g g' r r') => GHFunctor g g' (l :+: r) (l' :+: r') where
55+
ghmap f = \case
56+
L1 l -> L1 $ ghmap f l
57+
R1 r -> R1 $ ghmap f r
58+
59+
instance GHFunctor g g' f f' => GHFunctor g g' (M1 i c f) (M1 i c f') where
60+
ghmap f = M1 . ghmap f . unM1
61+
62+
instance GHFunctor g g' (Rec1 g) (Rec1 g') where
63+
ghmap f = Rec1 . f . unRec1
64+
65+
instance HFunctor sig => GHFunctor g g' (Rec1 (sig g)) (Rec1 (sig g')) where
66+
ghmap f = Rec1 . hmap f . unRec1

src/Syntax/Module.hs

+4-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ joinr :: (RightModule f, Monad m) => f m (m a) -> f m a
7575
joinr = (>>=* id)
7676

7777

78-
instance (RightModule f, RightModule g) => RightModule (f Sum.:+: g)
78+
instance (RightModule f, RightModule g) => RightModule (f Sum.:+: g) where
79+
s >>=* f = case s of
80+
Sum.L l -> Sum.L (l >>=* f)
81+
Sum.R r -> Sum.R (r >>=* f)
7982

8083

8184
class (HFunctor f, forall g . Functor g => Functor (f g)) => LeftModule f where

src/Syntax/Sum.hs

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1-
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, PolyKinds, TypeOperators #-}
1+
{-# LANGUAGE ConstraintKinds, DeriveGeneric, DeriveTraversable, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, PolyKinds, TypeFamilies, TypeOperators #-}
22
module Syntax.Sum
33
( -- * Sum syntax
44
(:+:)(..)
55
, unSum
66
-- * Membership
77
, Inject(..)
88
, Project(..)
9+
, Member
10+
, Members
911
) where
1012

11-
import Control.Effect.Sum ((:+:)(..))
13+
import Data.Kind (Constraint)
14+
import GHC.Generics (Generic1)
15+
16+
data (f :+: g) (m :: * -> *) k
17+
= L (f m k)
18+
| R (g m k)
19+
deriving (Eq, Foldable, Functor, Generic1, Ord, Show, Traversable)
20+
21+
infixr 4 :+:
1222

1323
unSum :: (f t a -> b) -> (g t a -> b) -> (f :+: g) t a -> b
1424
unSum f _ (L l) = f l
@@ -65,3 +75,15 @@ instance {-# OVERLAPPABLE #-}
6575
=> Project t (l :+: r) where
6676
prj (R r) = prj r
6777
prj _ = Nothing
78+
79+
80+
type Member sub sup = (Inject sub sup, Project sub sup)
81+
82+
-- | Decompose sums on the left into multiple 'Member' constraints.
83+
--
84+
-- Note that while this, and by extension 'Control.Algebra.Has', can be used to group together multiple membership checks into a single (composite) constraint, large signatures on the left can slow compiles down due to [a problem with recursive type families](https://gitlab.haskell.org/ghc/ghc/issues/8095).
85+
--
86+
-- @since 1.0.0.0
87+
type family Members sub sup :: Constraint where
88+
Members (l :+: r) u = (Members l u, Members r u)
89+
Members t u = Member t u

src/Syntax/Term.hs

+4-8
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ module Syntax.Term
1212
, foldTerm
1313
) where
1414

15-
import Control.Algebra (Algebra(..))
1615
import Control.Applicative (Alternative(..))
1716
import Control.Monad ((<=<), ap)
17+
import Syntax.Algebra (Algebra(..))
1818
import Syntax.Fin
1919
import Syntax.Functor
2020
import Syntax.Module
@@ -64,9 +64,7 @@ instance RightModule sig
6464

6565

6666
hoistTerm
67-
:: ( HFunctor sig
68-
, forall g . Functor g => Functor (sig g)
69-
)
67+
:: HFunctor sig
7068
=> (forall m x . sig m x -> sig' m x)
7169
-> (Term sig a -> Term sig' a)
7270
hoistTerm f = cata Var (Alg . f)
@@ -80,17 +78,15 @@ prjTerm :: (Alternative m, Project sub sig) => Term sig a -> m (sub (Term sig) a
8078
prjTerm = maybe empty pure . (prj <=< unTerm)
8179

8280

83-
iter :: (Algebra sig m, forall f . Functor f => Functor (sig f)) => Term sig a -> m a
81+
iter :: Algebra sig m => Term sig a -> m a
8482
iter = \case
8583
Var a -> pure a
8684
Alg t -> alg (hmap iter t)
8785

8886

8987
cata
9088
:: forall sig m a
91-
. ( HFunctor sig
92-
, forall g . Functor g => Functor (sig g)
93-
)
89+
. HFunctor sig
9490
=> (forall x . x -> m x)
9591
-> (forall x . sig m x -> m x)
9692
-> (Term sig a -> m a)

src/Syntax/Trans/Scope.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ unScopeT (ScopeT s) = s
4141
instance HFoldable t => HFoldable (ScopeT a t) where
4242
hfoldMap f = getAlt . foldMap (Alt . f) <=< hfoldMap f . unScopeT
4343

44-
instance (HFunctor t, forall g . Functor g => Functor (t g)) => HFunctor (ScopeT a t) where
44+
instance HFunctor t => HFunctor (ScopeT a t) where
4545
hmap f = ScopeT . hmap f . fmap (fmap f) . unScopeT
4646

4747
instance HTraversable t => HTraversable (ScopeT a t) where
@@ -67,7 +67,7 @@ instance (Monad (t f), MonadTrans t, Monad f) => Monad (ScopeT a t f) where
6767
instance MonadTrans f => MonadTrans (ScopeT a f) where
6868
lift = ScopeT . lift . pure . F
6969

70-
instance (HFunctor t, forall g . Functor g => Functor (t g)) => RightModule (ScopeT b t) where
70+
instance HFunctor t => RightModule (ScopeT b t) where
7171
ScopeT s >>=* k = ScopeT (fmap (>>= k) <$> s)
7272

7373

src/Syntax/Traversable.hs

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import qualified Syntax.Sum as Sum
1111

1212
class ( HFoldable sig
1313
, HFunctor sig
14-
, forall g . Functor g => Functor (sig g)
1514
, forall g . Traversable g => Traversable (sig g)
1615
)
1716
=> HTraversable sig where
@@ -25,7 +24,10 @@ class ( HFoldable sig
2524
-> (sig g a -> f (sig h a))
2625
htraverse f = fmap to1 . ghtraverse f . from1
2726

28-
instance (HTraversable l, HTraversable r) => HTraversable (l Sum.:+: r)
27+
instance (HTraversable l, HTraversable r) => HTraversable (l Sum.:+: r) where
28+
htraverse f = \case
29+
Sum.L l -> Sum.L <$> htraverse f l
30+
Sum.R r -> Sum.R <$> htraverse f r
2931

3032

3133
class GHTraversable g g' rep rep' where

0 commit comments

Comments
 (0)