packages feed

derive-topdown 0.0.1.0 → 0.0.2.0

raw patch · 7 files changed

+204/−6 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Derive.Superclass: deriving_superclasses :: Name -> Name -> Q [Dec]
+ Data.Derive.Superclass: gnds :: Name -> Name -> Q [Dec]
+ Data.Derive.Superclass: newtype_deriving_superclasses :: Name -> Name -> Q [Dec]
+ Data.Derive.Superclass: strategy_deriving_superclasses :: DerivStrategy -> Name -> Name -> Q [Dec]
+ Data.Derive.TopDown: AnyclassStrategy :: DerivStrategy
+ Data.Derive.TopDown: NewtypeStrategy :: DerivStrategy
+ Data.Derive.TopDown: StockStrategy :: DerivStrategy
+ Data.Derive.TopDown: anyclass :: DerivStrategy
+ Data.Derive.TopDown: data DerivStrategy
+ Data.Derive.TopDown: newtype_ :: DerivStrategy
+ Data.Derive.TopDown: stock :: DerivStrategy
+ Data.Derive.TopDown: strategy_deriving :: DerivStrategy -> Name -> Name -> Q [Dec]
+ Data.Derive.TopDown: strategy_derivings :: DerivStrategy -> [Name] -> Name -> Q [Dec]
+ Data.Derive.TopDown: strategy_derivingss :: DerivStrategy -> [Name] -> [Name] -> Q [Dec]

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ derive-topdown ======+derive-topdown-0.0.2.0+--------------+- `0.0.2.0`+	* Add deriving superclass functions. When you want to derive a class instance, not necessary to derive all its superclasses. derive-topdown-0.0.1.0 -------------- - `0.0.1.0`
README.md view
@@ -90,9 +90,26 @@ 	        ... You can use this this function with [`derive`](http://hackage.haskell.org/package/derive) package. -### 4. Deriving with strategies in GHC 8.2+### 4. Deriving the superclasses+`Data.Derive.Superclass` provides `deriving_superclasses`, `strategy_deriving_superclasses` and newtype_deriving_superclasses, gnds can be used to derive class instance and its superclass instances. ++For example:++	    data A = A+	    deriving_superclasses ''Ord ''A++You wil get:++	    deriving_superclasses ''Ord ''A+	  ======>+	    deriving instance Ord A+	    deriving instance Eq A+++### 5. Deriving with strategies in GHC 8.2 If you want to specify the strategy for deriving mechanism then `strategy_deriving`, `strategy_derivings` and `strategy_derivingss` can be used. The 3 strategies for deriving `StockStrategy`,`AnyclassStrategy`,`NewtypeStrategy` are exposed when you import `TopDown`. They can be written as `stock`, `anyclass` as the default grammar. For `newtype`, you can write it as `newtype_` since there is a clison with `newtype` for data declaration. Please see [DerivingStrategies](https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies)+  #### **NOTE**:  About deriving instances of Typeable There is a bug with `isInstance` function when working with Typeable class. See [`ticket #11251`](https://ghc.haskell.org/trac/ghc/ticket/11251). So there might be problems if you really want to derive `Typeable` class. However, this bug should affect you too much here since GHC now has `AutoDeriveTypeable` extension, which means you should never derive `Typeable` manually.
derive-topdown.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                derive-topdown-version:             0.0.1.0+version:             0.0.2.0 synopsis:            Help Haskellers derive class instances for composited data types. description:         This package will make it easier to derive class instance for complex composited data types by using Template Haskell. license:             BSD3@@ -21,7 +21,8 @@   location: git://github.com/HaskellZhangSong/derive-topdown.git                       library-  exposed-modules:    Data.Derive.TopDown+  exposed-modules:    Data.Derive.TopDown,+                      Data.Derive.Superclass   other-modules:      Data.Derive.TopDown.Lib,                       Data.Derive.TopDown.Standalone,                       Data.Derive.TopDown.Instance
+ src/Data/Derive/Superclass.hs view
@@ -0,0 +1,153 @@+{-|++Module      : Data.Derive.TopDown+Description : Help Haskellers derive class instances for composited data types.+Copyright   : (c) songzh+License     : BSD3+Maintainer  : Haskell.Zhang.Song@hotmail.com+Stability   : experimental++Class dependencies can be complex sometimes, such as numeric and monadic classes. Making instances of them can be very tedious. Functoins in this module will help you derive the specified class instance with all the superclass instances of it.  For using this module, you may need to enable the following langauge extensions: @TemplateHaskell@, @StandaloneDeriving@, @DeriveGeneric@, @DeriveDataTypeable@, @GeneralizedNewtypeDeriving@, @DeriveAnyClass@++You may also need to enable GHC options @-ddump-splices@. ++For example:++> data A = A+> deriving_superclasses ''Ord ''A++You wil get:++>    deriving_superclasses ''Ord ''A+>  ======>+>    deriving instance Ord A+>    deriving instance Eq A++'Eq' is automatically derived when 'Ord' is derived, since 'Eq' is a superclass of 'Ord'++> newtype IO_ a = IO_ (IO a)+> strategy_deriving_superclasses newtype_ ''MonadIO ''IO_ ++You will get:++>    strategy_deriving_superclasses newtype_ ''MonadIO ''IO_+>  ======>+>    deriving newtype instance MonadIO IO_+>    deriving newtype instance Monad IO_+>    deriving newtype instance Applicative IO_+>    deriving newtype instance Functor IO_++Appearently, @Functor f => Applicative f => Monad f => MonadIO f@++> newtype F32 = F32 Float+> newtype_deriving_superclasses ''RealFloat ''F32++You will get:++>    newtype_deriving_superclasses ''RealFloat ''F32+>  ======>+>    deriving newtype instance RealFloat F32+>    deriving newtype instance RealFrac F32+>    deriving newtype instance Real F32+>    deriving newtype instance Num F32+>    deriving newtype instance Ord F32+>    deriving newtype instance Eq F32+>    deriving newtype instance Fractional F32+>    deriving newtype instance Floating F32++Some of these examples are from [#13668](https://ghc.haskell.org/trac/ghc/ticket/13668).+-}++module Data.Derive.Superclass +       (deriving_superclasses,+#if __GLASGOW_HASKELL__ >= 802        +        strategy_deriving_superclasses,+        newtype_deriving_superclasses,+        gnds+#endif+        )where++import Data.Derive.TopDown.Lib+import Language.Haskell.TH+import Language.Haskell.TH.Lib+import Debug.Trace+import Control.Monad+import Data.List+import Control.Monad.Trans.State+import Control.Monad.Trans+import Data.Maybe+import Language.Haskell.TH.Ppr++isHigherOrderClass :: Name -> Q Bool+isHigherOrderClass ty = do+                    cla <- reify ty+                    case cla of+                        ClassI (ClassD _ _ vars _ _) _ -> do+                                                    let (KindedTV _ k) = head vars+                                                    if k == StarT+                                                        then return True+                                                        else return False+                        _ -> error $ show ty ++ " is not a class"+                    +++deriving_superclasses :: Name -> Name -> Q [Dec]+deriving_superclasses cn tn = do+                            a <- evalStateT (deriving_superclasses' Nothing cn tn) []+                            return a++#if __GLASGOW_HASKELL__ >= 802+strategy_deriving_superclasses :: DerivStrategy -> Name -> Name -> Q [Dec]+strategy_deriving_superclasses st cn tn = do+                            a <- evalStateT (deriving_superclasses' (Just st) cn tn) []+                            return a++-- |Use newtype strategy to derive all the superclass instances.+newtype_deriving_superclasses = strategy_deriving_superclasses NewtypeStrategy++-- |Abbreviation for @newtype_deriving_superclasses@.+gnds = newtype_deriving_superclasses+#endif++#if __GLASGOW_HASKELL__ >= 802+deriving_superclasses' :: Maybe DerivStrategy -> Name -> Name -> StateT [Type] Q [Dec]+deriving_superclasses' st cn tn = do+#else+deriving_superclasses' :: Name -> Name -> StateT [Type] Q [Dec]+deriving_superclasses' cn tn = do+#endif+                    (tvbs,cons) <- getTyVarCons cn tn+                    let tp = AppT (ConT cn) (ConT tn) +                    types <- get+                    isCnHighOrderClass <- lift $ isHigherOrderClass cn+                    classContext <- if isCnHighOrderClass+                                        then lift $ generateClassContext cn tn+                                        else return Nothing+                    --+                    let Just a = classContext+                    let typeNames = map getTVBName tvbs+                    isIns <- lift $ isInstance' cn [ConT tn]+                    let context = maybeToList classContext+                    if (isIns || elem tp types)+                        then return []+                        else+                            do+                            topClassInstance <- return [StandaloneDerivD +#if __GLASGOW_HASKELL__ >= 802+                                                            st+#endif+                                                            context tp]++                            modify (tp:)+                            ci <- lift $ reify cn+                            case ci of+                                ClassI (ClassD ctx _ _ _ _) _ -> do+                                                    let classConTs = map getTypeConstructor ctx+                                                    ss <- fmap (nub.concat) $ forM classConTs $ \(ConT className) -> do+                                                                                    superclass_decls <- deriving_superclasses' +#if __GLASGOW_HASKELL__ >= 802+                                                                                                            st+#endif+                                                                                                            className tn+                                                                                    return superclass_decls+                                                    return $ topClassInstance ++ ss
src/Data/Derive/TopDown.hs view
@@ -8,8 +8,12 @@ Stability   : experimental  -@derive-topdown@ will make it easier to derive class instance for complex composited data types by using Template Haskell. For example:+@derive-topdown@ will make it easier to derive class instance for complex composited data types by using Template Haskell. For using this module, you may need to enable the following langauge extensions: @TemplateHaskell@, @StandaloneDeriving@, @DeriveGeneric@, @DeriveDataTypeable@, @GeneralizedNewtypeDeriving@,@ DeriveAnyClass@. +You may also need to enable GHC options @-ddump-splices@. ++For example:+ > data Gender = Male | Female > type Age = Int > data Person a = P {name :: String , age :: Int, gender :: Gender}@@ -67,8 +71,8 @@   module Data.Derive.TopDown.Instance,   module Data.Derive.TopDown.TH #if __GLASGOW_HASKELL__ >= 802-   ,DerivStrategy(StockStrategy,AnyclassStrategy,NewtypeStrategy)    ,stock, anyclass, newtype_+   ,DerivStrategy(StockStrategy,AnyclassStrategy,NewtypeStrategy) #endif   ) @@ -82,7 +86,7 @@  #if __GLASGOW_HASKELL__ >= 802 {-|-@sock@ and @anyclass@ are still allow to be used as functions or arguments. See <https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies>+The name @sock@ and @anyclass@ are still allowed to be used as functions or arguments. See <https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies> -} stock     = StockStrategy anyclass  = AnyclassStrategy
src/Data/Derive/TopDown/Lib.hs view
@@ -9,6 +9,7 @@  , TypeName  , decType  , DecTyType(..)+ ,getTypeConstructor  ) where  import Language.Haskell.TH@@ -230,3 +231,6 @@                                                 0 -> return StarT                                                 n -> return (foldr1 (\x y -> AppT (AppT ArrowT x) y) (replicate arity StarT)) +getTypeConstructor :: Type -> Type+getTypeConstructor (AppT a1 a2) = getTypeConstructor a1+getTypeConstructor a = a
tests/Test.hs view
@@ -22,6 +22,8 @@ import Language.SQL.SimpleSQL.Syntax import Data.Word import Text.PrettyPrint.GenericPretty+import Data.Derive.Superclass+import Control.Monad.IO.Class  -- Test for deriving strategy newtype A = A (Int,B)@@ -168,6 +170,19 @@  derivings [''Out, ''Generic] ''QueryExpr +-- Test for deriving super classes++newtype IO_ a = IO_ (IO a)++strategy_deriving_superclasses newtype_ ''MonadIO ''IO_ ++newtype F32 = F32 Float++newtype_deriving_superclasses ''RealFloat ''F32++data E = E++deriving_superclasses ''Ord ''E  main = putStrLn "Test passed"