effectful-th (empty) → 1.0.0.0
raw patch · 6 files changed
+729/−0 lines, 6 filesdep +basedep +containersdep +effectful
Dependencies added: base, containers, effectful, effectful-th, exceptions, template-haskell, th-abstraction
Files
- CHANGELOG.md +2/−0
- LICENSE +64/−0
- README.md +173/−0
- effectful-th.cabal +77/−0
- src/Effectful/TH.hs +270/−0
- tests/ThTests.hs +143/−0
+ CHANGELOG.md view
@@ -0,0 +1,2 @@+# effectful-th-1.0.0.0 (2022-07-13)+* Initial release.
+ LICENSE view
@@ -0,0 +1,64 @@+Copyright (c) 2021-2022, Andrzej Rybczak++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Andrzej Rybczak nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++This software incorporates code from the cleff package (available from+https://hackage.haskell.org/package/cleff) under the following license:++Copyright Xy Ren (c) 2021++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Xy Ren nor the names of other contributors+ may be used to endorse or promote products derived from this+ software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,173 @@+# effectful++[](https://github.com/haskell-effectful/effectful/actions?query=branch%3Amaster)+[](https://hackage.haskell.org/package/effectful)+[](https://packdeps.haskellers.com/feed?needle=andrzej@rybczak.net)+[](https://www.stackage.org/lts/package/effectful)+[](https://www.stackage.org/nightly/package/effectful)+++<img src="https://user-images.githubusercontent.com/387658/127747903-f728437f-2ee4-47b8-9f0c-5102fd44c8e4.png" width="128">++An easy to use, fast extensible effects library with seamless integration with+the existing Haskell ecosystem.++Main features:++1. Very fast+ ([benchmarks](https://github.com/haskell-effectful/effectful/tree/master/benchmarks/README.md)).++2. Easy to use API (comparable with usage of the [MonadUnliftIO](https://hackage.haskell.org/package/unliftio-core/docs/Control-Monad-IO-Unlift.html#t:MonadUnliftIO) class).++3. Correct semantics in presence of runtime exceptions (no more discarded state+ updates).++4. Seamless integration with the existing ecosystem (`exceptions`,+ `monad-control`, `unliftio-core`, `resourcet` etc.).++5. Support for thread local and shared state (e.g. `StateT` provides a thread+ local state, while `MVar` holds a shared state, both approaches have their+ merits).++6. Support for statically (implementation determined at compile time) and+ dynamically (implementation determined at run time) dispatched effects.++## Motivation++Do we really need yet another library for handling effects? There's+[freer-simple](https://hackage.haskell.org/package/freer-simple),+[fused-effects](https://hackage.haskell.org/package/fused-effects),+[polysemy](https://hackage.haskell.org/package/polysemy),+[eff](https://github.com/hasura/eff) and probably a few more.++Unfortunately, of all of them only `eff` is a promising proposition because of+reasonable performance characteristics (see the talk [Effects for+Less](https://www.youtube.com/watch?v=0jI-AlWEwYI) for more information) and+potential for good interoperability with the existing ecosystem.++The second point is arguably the most important, because it allows focusing on+things that matter instead of reinventing all kinds of wheels, hence being a+necessary condition for broader adoption of the library.++However, `eff` uses delimited continuations underneath, which:++- Are not yet supported by GHC (though [the+proposal](https://github.com/ghc-proposals/ghc-proposals/pull/313) for including+support for them has been accepted).++- Are quite hard to understand.++- Make the library "too powerful" in a sense as it faces+ [a](https://github.com/hasura/eff/issues/13)+ [few](https://github.com/hasura/eff/issues/7)+ [issues](https://github.com/hasura/eff/issues/12) with no clear path towards+ their resolution.++### What about `mtl`?++It's true that its "effects as classes" approach is widely known and used often.++However:++- `mtl` style effects are+ [slow](https://github.com/haskell-effectful/effectful/tree/master/benchmarks/README.md).++- The majority of popular monad transformers (except `ReaderT`) used for effect+ implementations are rife with [subtle+ issues](https://github.com/haskell-effectful/effectful/tree/master/transformers.md).++These are problematic enough that the [ReaderT design+pattern](https://www.fpcomplete.com/blog/2017/06/readert-design-pattern/) was+invented. Its fundamentals are solid, but it's not an effect system.++A solution? Use the `ReaderT` pattern as a base and build around it to make an+extensible effects library! This is where `effectful` comes in. The `Eff` monad+it uses is essentially a `ReaderT` over `IO` on steroids, allowing us to extend+its environment with data types representing effects.++This concept is quite simple, so:++- It's reasonably easy to understand what is going on under the hood.++- The `Eff` monad being a reader allows for seamless interoperability with+ ubiquitous classes such as `MonadBaseControl` and `MonadUnliftIO` and solves+ [issues](https://github.com/haskell-effectful/effectful/tree/master/transformers.md)+ of monad transformers mentioned above.++What is more, the `Eff` monad is concrete, so GHC has many possibilities for+optimization, which results in a very fast code at a default optimization+level. There is no need to mark every function `INLINE` or enable additional+optimization passes, it just works.++### Any downsides?++As always, there's no free lunch. The `Eff` monad doesn't support `NonDet` nor+`Coroutine` effects. However, the `NonDet` effect in existing libraries is+[broken](https://github.com/lexi-lambda/eff/blob/8c4df4bf54faf22456354be18095b14825be5e85/notes/semantics-zoo.md)+and none of the ones with support for higher order effects provide the+`Coroutine` effect, so arguably it's not a big loss.++If you need such capability in your application, there are well established+libraries such as [conduit](https://hackage.haskell.org/package/conduit) or+[list-t](https://hackage.haskell.org/package/list-t) that can be used with+`effectful` without any issues.++### Summary++`effectful` is an extensible effects library that aims to replace "boring"+transformer stacks (which consist of a dozen of newtype'd `ExceptT`, `ReaderT`,+`StateT` and `WriterT` transformers) and their derivatives by providing+equivalent effects with improved semantics, performance and usability (it also+makes it easy to reuse them for your own effects). It doesn't try to make monad+transformers obsolete, so you're free to use it with `ConduitT`, `ContT`,+`ListT` etc. when necessary.++## Package structure++The effect system is split among several libraries:++- The [`effectful-core`](https://hackage.haskell.org/package/effectful-core)+ library contains the core of the effect system along with the basic+ effects. It aims for a small dependency footprint and provides building blocks+ for more advanced effects.++- The [`effectful-plugin`](https://hackage.haskell.org/package/effectful-plugin)+ library provides an optional GHC plugin for improving disambiguation of+ effects (see+ [here](https://github.com/haskell-effectful/effectful/blob/master/effectful-plugin/README.md)+ for more information).++- The [`effectful-th`](https://hackage.haskell.org/package/effectful-th) library+ provides utilities for generating bits of effect-related boilerplate via+ Template Haskell.++- The [`effectful`](https://hackage.haskell.org/package/effectful) library+ re-exports public modules of `effectful-core` and additionally provides most+ features of the `unliftio` library divided into appropriate effects.++## Example++A `Filesystem` effect with two handlers, one that runs in `IO` and another that+uses an in-memory virtual file system can be found+[here](https://github.com/haskell-effectful/effectful/blob/master/effectful/examples/FileSystem.hs).++## Resources++Resources that inspired the rise of this library and had a lot of impact on its+design.++Talks:++* [Effects for Less](https://www.youtube.com/watch?v=0jI-AlWEwYI) by Alexis King.++* [Monad Transformer State](https://www.youtube.com/watch?v=KZIN9f9rI34) by Michael Snoyman.++Blog posts:++* [ReaderT design pattern](https://www.fpcomplete.com/blog/2017/06/readert-design-pattern/) by Michael Snoyman.++* [Exceptions Best Practices](https://www.fpcomplete.com/blog/2016/11/exceptions-best-practices-haskell/) by Michael Snoyman.++----------------------------------------++<div>Icons made by <a href="https://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
+ effectful-th.cabal view
@@ -0,0 +1,77 @@+cabal-version: 2.4+build-type: Simple+name: effectful-th+version: 1.0.0.0+license: BSD-3-Clause+license-file: LICENSE+category: Control+maintainer: andrzej@rybczak.net+author: Andrzej Rybczak+synopsis: Template Haskell utilities for the effectful library.++description: Generate functions for performing operations of dynamically+ dispatched effects via Template Haskell.++extra-source-files:+ CHANGELOG.md+ README.md++tested-with: GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.3 || ==9.4.1++bug-reports: https://github.com/haskell-effectful/effectful/issues+source-repository head+ type: git+ location: https://github.com/haskell-effectful/effectful.git++common language+ ghc-options: -Wall -Wcompat -Wno-unticked-promoted-constructors++ default-language: Haskell2010++ default-extensions: BangPatterns+ ConstraintKinds+ DataKinds+ DeriveFunctor+ DeriveGeneric+ FlexibleContexts+ FlexibleInstances+ GADTs+ GeneralizedNewtypeDeriving+ LambdaCase+ MultiParamTypeClasses+ NoStarIsType+ RankNTypes+ RecordWildCards+ RoleAnnotations+ ScopedTypeVariables+ StandaloneDeriving+ TupleSections+ TypeApplications+ TypeFamilies+ TypeOperators++library+ import: language++ build-depends: base >= 4.13 && < 5+ , containers >= 0.6+ , effectful >= 1.0.0.0 && < 1.0.1.0+ , exceptions >= 0.10.4+ , template-haskell >= 2.15 && < 2.20+ , th-abstraction >= 0.4 && < 0.5++ hs-source-dirs: src++ exposed-modules: Effectful.TH++test-suite th-tests+ import: language++ build-depends: base+ , effectful+ , effectful-th++ hs-source-dirs: tests++ type: exitcode-stdio-1.0+ main-is: ThTests.hs
+ src/Effectful/TH.hs view
@@ -0,0 +1,270 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskellQuotes #-}+-- | Generate functions for performing operations of dynamically dispatched+-- effects via Template Haskell.+module Effectful.TH+ ( makeEffect+ , makeEffect_+ ) where++import Control.Monad+import Data.Char (toLower)+import Data.Foldable (foldl')+import Data.Maybe+import Language.Haskell.TH+import Language.Haskell.TH.Datatype+import Language.Haskell.TH.Datatype.TyVarBndr+import qualified Data.Map.Strict as Map++import Effectful+import Effectful.Dispatch.Dynamic++-- | For an effect data type @E@, @'makeEffect' E@ generates the appropriate+-- instance of 'DispatchOf' as well as functions for performing operations of+-- @E@ by 'send'ing them to the effect handler.+--+-- >>> :{+-- data E :: Effect where+-- Op1 :: Int -> m a -> E m a+-- Op2 :: IOE :> es => Int -> E (Eff es) ()+-- Op3 :: (forall r. m r -> m r) -> E m Int+-- makeEffect ''E+-- :}+--+-- >>> :kind! DispatchOf E+-- DispatchOf E :: Dispatch+-- = 'Dynamic+--+-- >>> :i op1+-- op1 :: (HasCallStack, E :> es) => Int -> Eff es a -> Eff es a+-- ...+--+-- >>> :i op2+-- op2 :: (HasCallStack, E :> es, IOE :> es) => Int -> Eff es ()+-- ...+--+-- >>> :i op3+-- op3 ::+-- (HasCallStack, E :> es) =>+-- (forall r. Eff es r -> Eff es r) -> Eff es Int+-- ...+--+-- The naming rule changes the first uppercase letter in the constructor name to+-- lowercase or removes the @:@ symbol in case of operators. Any fixity+-- annotations defined for the constructors are preserved for the corresponding+-- definitions.+makeEffect :: Name -> Q [Dec]+makeEffect = makeEffectImpl True++-- | Like 'makeEffect', but doesn't generate type signatures. This is useful+-- when you want to attach Haddock documentation to function signatures:+--+-- >>> :{+-- data Noop :: Effect where+-- Noop :: Noop m ()+-- makeEffect_ ''Noop+-- -- | Perform nothing at all.+-- noop :: Noop :> es => Eff es ()+-- :}+--+-- /Note:/ function signatures must be added /after/ the call to 'makeEffect_'.+makeEffect_ :: Name -> Q [Dec]+makeEffect_ = makeEffectImpl False++makeEffectImpl :: Bool -> Name -> Q [Dec]+makeEffectImpl makeSig effName = do+ checkRequiredExtensions+ info <- reifyDatatype effName+ dispatch <- do+ e <- getEff (ConT $ datatypeName info) (datatypeInstTypes info)+ let dispatchE = ConT ''DispatchOf `AppT` e+ dynamic = PromotedT 'Dynamic+ pure . TySynInstD $ TySynEqn Nothing dispatchE dynamic+ ops <- traverse (makeCon makeSig) (constructorName <$> datatypeCons info)+ pure $ dispatch : concat (reverse ops)+ where+ getEff :: Type -> [Type] -> Q Type+ getEff e = \case+ [m, r] -> do+ checkKind "the next to last" (ArrowT `AppT` StarT `AppT` StarT) m+ checkKind "the last" StarT r+ pure e+ (v : vs) -> getEff (e `AppT` forgetKind v) vs+ _ -> fail "The effect data type needs at least 2 type parameters"+ where+ forgetKind = \case+ SigT v _ -> v+ ty -> ty++ checkKind which expected = \case+ SigT (VarT _) k+ | k == expected -> pure ()+ | otherwise -> fail+ $ "Expected " ++ which ++ " type parameter to have a kind "+ ++ pprint expected ++ ", got " ++ pprint k+ -- Weird type, let it through and see what happens.+ _ -> pure ()++-- | Generate a single definition of an effect operation.+makeCon :: Bool -> Name -> Q [Dec]+makeCon makeSig name = do+ fixity <- reifyFixity name+ typ <- reify name >>= \case+ DataConI _ typ _ -> pure typ+ _ -> fail $ "Not a data constructor: " ++ nameBase name++ (actionParams, (effTy, ename, resTy)) <- extractParams typ++ -- The 'ename' can be either:+ --+ -- - A variable for the monad, in which case we need to generate the @es@+ -- variable and substitute it later for 'Eff es'.+ --+ -- - A variable 'es' for the local 'Eff es' if the monad parameter was locally+ -- substituted in the contructor.+ --+ -- For example in the following effect:+ --+ -- data E :: Effect where+ -- E1 :: Int -> E m ()+ -- E2 :: IOE :> es => E (Eff es) ()+ --+ -- Processing 'E1' will yield 'Right m', but 'E2' will yield 'Left es'.+ --+ -- In the first case we need to substitute the variable ourselves in a few+ -- places, but in the second we're good since it was already substituted.+ (esName, maybeMonadName) <- case ename of+ Left esName -> pure (esName, Nothing)+ Right monadName -> (, Just monadName) <$> newName "es"++ let fnName = mkName . toSmartConName $ nameBase name+ fnArgs <- traverse (const $ newName "x") actionParams++ let esVar = VarT esName++ substM :: Type -> Type+ substM = case maybeMonadName of+ Just m -> applySubstitution . Map.singleton m $ ConT ''Eff `AppT` esVar+ Nothing -> id++ (origActionVars, actionCtx) = extractCtx typ+ actionVars = case maybeMonadName of+ Just m -> filter ((m /=) . tvName) origActionVars+ ++ [kindedTVSpecified esName $ ListT `AppT` ConT ''Effect]+ Nothing -> origActionVars++#if MIN_VERSION_template_haskell(2,17,0)+ -- In GHC >= 9.0 it's possible to generate the following body:+ --+ -- e x1 .. xN = send (E @ty1 .. @tyN x1 .. xN)+ --+ -- because specificities of constructor variables are exposed.+ --+ -- This allows to generate functions for such effects:+ --+ -- type family F ty :: Type+ -- data AmbEff :: Effect where+ -- AmbEff :: Int -> AmbEff m (F ty)+ --+ -- Sadly the version for GHC < 9 will not compile due to ambiguity error.+ let fnBody =+ let tvFlag = \case+ PlainTV _ flag -> flag+ KindedTV _ flag _ -> flag++ tyApps = (`mapMaybe` origActionVars) $ \v -> case tvFlag v of+ InferredSpec -> Nothing+ SpecifiedSpec -> Just $ if maybeMonadName == Just (tvName v)+ then ConT ''Eff `AppT` esVar+ else VarT (tvName v)++ effCon = if makeSig+ then foldl' AppTypeE (ConE name) tyApps+ else ConE name+ in VarE 'send `AppE` foldl' (\f -> AppE f . VarE) effCon fnArgs+#else+ -- In GHC < 9.0, generate the following body:+ --+ -- e :: E v1 .. vN :> es => x1 -> .. -> xK -> E v1 .. vN (Eff es) r+ -- e x1 .. xK = send (E x1 .. xN :: E v1 .. vK (Eff es) r)+ let fnBody =+ let effOp = foldl' (\f -> AppE f . VarE) (ConE name) fnArgs+ effSig = effTy `AppT` (ConT ''Eff `AppT` esVar) `AppT` substM resTy+ in if makeSig+ then VarE 'send `AppE` SigE effOp effSig+ else VarE 'send `AppE` effOp+#endif+ let fnSig = ForallT actionVars+ (ConT ''HasCallStack : UInfixT effTy ''(:>) esVar : actionCtx)+ (makeTyp esVar substM resTy actionParams)++ let rest = FunD fnName [Clause (VarP <$> fnArgs) (NormalB fnBody) []]+ : maybeToList ((`InfixD` name) <$> fixity)+ (++ rest) <$> withHaddock name [SigD fnName fnSig | makeSig]++----------------------------------------+-- Helpers++toSmartConName :: String -> String+toSmartConName = \case+ (':' : xs) -> xs+ (x : xs) -> toLower x : xs+ _ -> error "empty constructor name"++extractCtx :: Type -> ([TyVarBndrSpec], Cxt)+extractCtx = \case+ ForallT vars ctx _ -> (vars, ctx)+ ty -> error $ "unexpected type: " ++ show ty++extractParams :: Type -> Q ([Type], (Type, Either Name Name, Type))+extractParams = \case+ ForallT _ _ ty -> extractParams ty+ SigT ty _ -> extractParams ty+ ParensT ty -> extractParams ty+ ArrowT `AppT` a `AppT` ty -> do+ (args, ret) <- extractParams ty+ pure (a : args, ret)+#if MIN_VERSION_template_haskell(2,17,0)+ MulArrowT `AppT` _ `AppT` a `AppT` ty -> do+ (args, ret) <- extractParams ty+ pure (a : args, ret)+#endif+ effTy `AppT` monadTy `AppT` resTy -> case monadTy of+ VarT monadName -> pure ([], (effTy, Right monadName, resTy))+ ConT eff `AppT` VarT esName+ | eff == ''Eff -> pure ([], (effTy, Left esName, resTy))+ ty -> fail $ "Invalid instantiation of the monad parameter: " ++ pprint ty+ ty -> fail $ "Unexpected type: " ++ pprint ty++makeTyp :: Type -> (Type -> Type) -> Type -> [Type] -> Type+makeTyp esVar substM resTy = \case+ [] -> ConT ''Eff `AppT` esVar `AppT` substM resTy+ (p : ps) -> ArrowT `AppT` substM p `AppT` makeTyp esVar substM resTy ps++withHaddock :: Name -> [Dec] -> Q [Dec]+#if MIN_VERSION_template_haskell(2,18,0)+withHaddock name dec = withDecsDoc+ ("Perform the operation '" ++ nameBase name ++ "'.") (pure dec)+#else+withHaddock _ dec = pure dec+#endif++checkRequiredExtensions :: Q ()+checkRequiredExtensions = do+ missing <- filterM (fmap not . isExtEnabled) exts+ let ppMissing = map (\ext -> "{-# LANGUAGE " <> show ext <> " #-}") missing+ unless (null missing) . fail . unlines $+ [ "Generating functions requires additional language extensions.\n"+ , "You can enable them by adding them to the 'default-extensions'"+ , "field in the .cabal file or the following pragmas to the beginning"+ , "of the source file:\n"+ ] ++ ppMissing+ where+ exts = [ FlexibleContexts+ , ScopedTypeVariables+#if MIN_VERSION_template_haskell(2,17,0)+ , TypeApplications+#endif+ , TypeFamilies+ , TypeOperators+ ]
+ tests/ThTests.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TemplateHaskell #-}+module Main where++import Data.Kind (Type)+import GHC.TypeLits++import Effectful+import Effectful.TH++main :: IO ()+main = pure () -- only compilation tests++data SimpleADT (m :: Type -> Type) (a :: Type)+ = SimpleADTC1 Int+ | SimpleADTC2 String++makeEffect ''SimpleADT++data ADTSyntax1 (m :: Type -> Type) (a :: Type)+ = a ~ Int => ADTSyntax1C String++makeEffect ''ADTSyntax1++data ADTSyntax2 (m :: Type -> Type) (a :: Type)+ = a ~ Int => ADTSyntax2C1 Int+ | a ~ String => ADTSyntax2C2 String++makeEffect ''ADTSyntax2++data ADTSyntax3 (m :: Type -> Type) (a :: Type)+ = Show a => ADTSyntax3C a++makeEffect ''ADTSyntax3++data GADTSyntax :: Effect where+ GADTSyntaxC1 :: Int -> GADTSyntax m Int+ GADTSyntaxC2 :: String -> GADTSyntax m String+ GADTSyntaxC3 :: IOE :> es => Bool -> GADTSyntax (Eff es) a++makeEffect ''GADTSyntax++data Fields (m :: Type -> Type) (a :: Type)+ = FieldsC { fieldsCF1 :: Int, fieldsCF2 :: String }++makeEffect ''Fields++newtype Newtype1 (m :: Type -> Type) (a :: Type)+ = Newtype1C Int++makeEffect ''Newtype1++newtype Newtype2 :: Effect where+ Newtype2C :: String -> Newtype2 m a++makeEffect ''Newtype2++data Instance = ADTI | GADTI | NTI | MMI++data family Family (s :: Instance) (m :: Type -> Type) a++data instance Family 'ADTI _ _ = ADTIC1 Int | ADTIC2 String+makeEffect 'ADTIC1++data instance Family 'GADTI _ _ where+ GADTIC1 :: Int -> Family 'GADTI m Int+ GADTIC2 :: String -> Family 'GADTI m String+makeEffect 'GADTIC1++newtype instance Family 'NTI _ _ = NTIC Int+makeEffect 'NTIC++data instance Family 'MMI m (_ m) where+ MMIC1 :: f m -> Family 'MMI m (f m)+ MMIC2 :: (forall x. m x -> m (f m)) -> Family 'MMI m (f m)++makeEffect 'MMIC1++data Complex :: Effect where+ Mono :: Int -> Complex m Bool+ Poly :: a -> Complex m a+ PolyIn :: a -> Complex m Bool+ PolyOut :: Int -> Complex m a+ Lots :: a -> b -> c -> d -> e -> f -> Complex m ()+ Nested :: Maybe b -> Complex m (Maybe a)+ MultiNested :: (Maybe a, [b]) -> Complex m (Maybe a, [b])+ Existential :: (forall e. e -> Maybe e) -> Complex m a+ LotsNested :: Maybe a -> [b] -> (c, c) -> Complex m (a, b, c)+ Dict :: Ord a => a -> Complex m a+ MultiDict :: (Eq a, Ord b, Enum a, Num c)+ => a -> b -> c -> Complex m ()+ IndexedMono :: f 0 -> Complex m Int+ IndexedPoly :: forall f (n :: Nat) m . f n -> Complex m (f (n + 1))+ IndexedPolyDict :: KnownNat n => f n -> Complex m Int++makeEffect ''Complex++data HOEff :: Effect where+ EffArgMono :: m () -> HOEff m ()+ EffArgPoly :: m a -> HOEff m a+ EffArgComb :: m a -> (m a -> m b) -> HOEff m b+ EffRank2 :: (forall x. m x -> m (Maybe x)) -> HOEff m a++makeEffect ''HOEff++data ComplexEffArgs b c :: Effect where+ EffMono :: Int -> ComplexEffArgs Int String m Bool+ EffPoly1 :: a -> ComplexEffArgs a b m a+ EffPoly2 :: a -> ComplexEffArgs a (Maybe a) m Bool+ EffPolyFree :: String -> ComplexEffArgs a b m Int+ EffSame1 :: ComplexEffArgs a a m a+ EffSame2 :: ComplexEffArgs b b m a+ EffHO :: m b -> ComplexEffArgs b Int m String++makeEffect ''ComplexEffArgs++data HKEffArgs f g :: Effect where+ HKRank2 :: (forall x . f x -> g x) -> HKEffArgs f g m a++makeEffect ''HKEffArgs++data ByCon :: Effect where+ ByConA :: Int -> ByCon m String+ ByConB :: Int -> ByCon m String++makeEffect 'ByConA++data ByField :: Effect where+ ByFieldA :: { byFieldAf :: Int } -> ByField m Int+ ByFieldB :: { byFieldBf :: Int } -> ByField m Int++makeEffect 'byFieldAf++type family F ty+data AmbEff :: Effect where+ AmbEff :: Int -> AmbEff m (F ty)++-- This only works in GHC >= 9, otherwise the 'ty' variable is ambiguous.+#if __GLASGOW_HASKELL__ >= 900+makeEffect 'AmbEff+#endif