impl (empty) → 0.1.0.0
raw patch · 5 files changed
+118/−0 lines, 5 filesdep +basedep +impldep +named
Dependencies added: base, impl, named, template-haskell
Files
- Impl.hs +28/−0
- Impl/Utils.hs +26/−0
- example/Monad/Foo.hs +8/−0
- example/Monad/Impl.hs +15/−0
- impl.cabal +41/−0
+ Impl.hs view
@@ -0,0 +1,28 @@+{-# OPTIONS_HADDOCK show-extensions #-}+-- | This small but extensible framework facilitates defining complex defaulting rules that are not handled by @DefaultSignatures@, and reducing the overhead of giving instances to new datatypes by generating superclasses. One reason we might want this is when a superclass wants to be given a default by two different subclasses (ex: @Bifunctor@ and @Profunctor@ both could generate @Functor@ instances). See the @example@ internal library for how to implement instances of 'Impl'.+module Impl (Impl(..),NamedMethods+ -- * Reexports+ ,type (:->),TypeQ,(!) ,type (:!), NamedF(Arg), arg+ ) where+import Language.Haskell.TH+import Named hiding (Name)+import GHC.TypeLits (Symbol)+import Impl.Utils+ +class Impl c where+ type Methods c :: [Symbol]+ -- | Instantiate the implementing class along with all its superclasses+ -- Ex: + --+ -- > impl @Monad [t|[]|]+ -- > ! #return [|\x -> [x]|]+ -- > ! #bind [|flip concatMap|]+ impl :: TypeQ -> NamedMethods c :-> DecsQ++-- | +type family NamedExpQ ss where+ NamedExpQ '[] = '[]+ NamedExpQ (s ': ss) = (s :! ExpQ) ': NamedExpQ ss++-- | "Named" TH 'Exp's for the class method implementations+type NamedMethods c = NamedExpQ (Methods c)
+ Impl/Utils.hs view
@@ -0,0 +1,26 @@+module Impl.Utils where+import Language.Haskell.TH++typeList :: [Type] -> Type+typeList = foldr (\t -> AppT (AppT PromotedConsT t)) PromotedNilT++-- | Converts a variable number of arguments into curried form. Ex:+--+-- >>> :!kind '[Int,String,Double] :-> IO ()+-- Int -> String -> Double -> IO ()+infixr 0 :->+type family as :-> r where+ (a ': as) :-> r = a -> as :-> r+ '[] :-> r = r++methodsFor :: Name -- ^ Typeclass name+ -> TypeQ -- ^ @ :: [Symbol]@+ +-- | Retrieve the method names of a typeclass as a typelevel list of @Symbol@s.+-- A good default for instantiating the 'Methods' type,+-- which is robust against changing method names+methodsFor n = do+ ClassI (ClassD _ _ _ _ (map sigSym -> ss)) _ <- reify n+ return (typeList ss )+ where sigSym (SigD (nameBase -> s) _) = LitT (StrTyLit s)+
+ example/Monad/Foo.hs view
@@ -0,0 +1,8 @@+module Monad.Foo where+import Monad.Impl++data Foo a = Foo a++impl @Monad [t|Foo|]+ ! #return [|Foo|]+ ! #bind [|\(Foo a) f -> f a|]
+ example/Monad/Impl.hs view
@@ -0,0 +1,15 @@+module Monad.Impl (module X) where+import Impl as X++instance Impl Monad where+ type Methods Monad = '["return","bind"]+ impl m (Arg return) (Arg bind) = [d|+ instance Monad $m where+ return = $return+ (>>=) = $bind+ instance Applicative $m where + pure = $return+ mf <*> ma = $bind mf $ \f -> $bind ma $ \a -> $return (f a)+ instance Functor $m where+ fmap f ma = $bind ma $ \a -> $return (f a)+ |]
+ impl.cabal view
@@ -0,0 +1,41 @@+cabal-version: 2.2+name: impl+homepage: https://github.com/exordium/impl#readme+version: 0.1.0.0+category: Development, Template Haskell+synopsis: Framework for defaulting superclasses+stability: cursed+bug-reports: https://github.com/exordium/impl/issues+author: Dai+maintainer: daig@sodality.cc+copyright: 2018 Sodality+license: MIT++source-repository head+ type: git+ location: https://github.com/exordium/impl++common x+ default-language: Haskell2010+ default-extensions: TypeFamilies, ViewPatterns, DataKinds, TypeOperators, AllowAmbiguousTypes, TypeApplications, OverloadedLabels, TemplateHaskell, PolyKinds+ build-depends: base ^>= 4.12.0.0++library+ import: x+ exposed-modules: Impl+ other-modules: Impl.Utils+ build-depends: template-haskell ^>= 2.14.0.0+ , named ^>= 0.2.0.0++Flag DumpExample+ Description: Show generated TH in example+ Default: False+ Manual: True++library example+ import: x+ hs-source-dirs: example+ exposed-modules: Monad.Impl, Monad.Foo+ if flag(DumpExample)+ ghc-options: -ddump-splices -dsuppress-uniques+ build-depends: impl