packages feed

derive-topdown-0.1.0.0: README.md

# derive-topdown
[![Hackage version](https://img.shields.io/hackage/v/derive-topdown.svg?label=Hackage)](https://hackage.haskell.org/package/derive-topdown) [![Stackage version](https://www.stackage.org/package/derive-topdown/badge/lts?label=Stackage)](https://www.stackage.org/package/derive-topdown)

This is a Haskell project which will derive type class instances from top for a composite data type.

## 1. Standalone deriving
There are functions named `deriving_`, `derivings`, `derivingss`. Please see the API for their types.

``` haskell
{-# LANGUAGE StandaloneDeriving,
    ConstraintKinds,
    UndecidableInstances,
    GADTs,
    TemplateHaskell,
    DeriveGeneric #-}
{-# OPTIONS_GHC -ddump-splices #-}

import Data.Derive.TopDown
import GHC.Generics
import Data.Binary
import Data.Aeson
import Data.Aeson.TH

data Gender = Male | Female
type Age = Int
data Person a = P {name :: String , age :: Int, gender :: Gender}
data Department a = D {dname :: String , 
                        head :: Person a, 
                        staff :: [Person a]}
data Company a = C {cname :: String, 
                    departments :: [Department a]}

derivings [''Eq, ''Ord, ''Generic] ''Company
```
You will get:
```haskell
derivings [''Eq, ''Ord, ''Generic] ''Company
======>
deriving instance Eq Gender
deriving instance Eq (Person a_acKV)
deriving instance Eq a_acKU => Eq (Department a_acKU)
deriving instance Eq a_acKT => Eq (Company a_acKT)
deriving instance Ord Gender
deriving instance Ord (Person a_acKV)
deriving instance Ord a_acKU => Ord (Department a_acKU)
deriving instance Ord a_acKT => Ord (Company a_acKT)
deriving instance Generic Gender
deriving instance Generic (Person a_acKV)
deriving instance Generic (Department a_acKU)
deriving instance Generic (Company a_acKT)
```
## 2. Empty Instances generation

For empty class instances deriving, `instance_`, `instances`, `instancess` are provided. We can use it in this way.

```haskell
instances [''Binary] ''Company
======>
instance Binary Gender
instance Binary (Person a_af50)
instance Binary a_af4Z => Binary (Department a_af4Z)
instance Binary a_af4Y => Binary (Company a_af4Y)
```
## 3. Usage with Template Haskell
For generating instances with a template Haskell function, `derivingTH`, `derivingTHs` and `derivingTHss` can be used:
```haskell
derivingTHs
    [(''ToJSON, deriveToJSON defaultOptions),
    (''FromJSON, deriveFromJSON defaultOptions)]
    ''Company
======>
instance ToJSON Gender where
    toJSON
    = \ value_amQG
        -> case value_amQG of {
                Male -> String (text-1.2.2.2:Data.Text.pack "Male")
                Female -> String (text-1.2.2.2:Data.Text.pack "Female") }
    toEncoding
    = \ value_amQH
        -> case value_amQH of {
                Male
                -> Data.Aeson.Encoding.Internal.text
                    (text-1.2.2.2:Data.Text.pack "Male")
                Female
                -> Data.Aeson.Encoding.Internal.text
                    (text-1.2.2.2:Data.Text.pack "Female") }
instance ToJSON a_amqg => ToJSON (Person a_amqg) where
    toJSON
    = \ value_amQy
    ...
    ...
```
You can use this this function with [`derive`](http://hackage.haskell.org/package/derive) package. However, it seems that this package is broken with GHC >= 802.

## 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:
```haskell
data A = A
deriving_superclasses ''Ord ''A
```
You wil get:
```haskell
deriving_superclasses ''Ord ''A
======>
deriving instance Ord A
deriving instance Eq A
```

Mutual recursive type decalrations need to derive superclass together as the following:
```haskell
fmap concat (sequence [(deriving_superclasses ''Ord ''T2), (deriving_superclasses ''Ord ''T3)])
```
In the code above, T2 and T3 are mutual recursive data types.

## 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
### Derive with breaks
The deriving process might be interrupted by a given list of type names. The generation process will stop on those give names. Please see the test case.

### **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 not affect you too much here since GHC now has `AutoDeriveTypeable` extension, which means you should never derive `Typeable` manually.

### **NOTE**: You cannot derive a type synonym.
`derive-topdown` will not work with `-XTypeSynonymInstances` language extension. The top node in the data declaration tree has to be a data or newtype.

More discussion about `derive-topdown`, please see [`ticket #10607`](https://ghc.haskell.org/trac/ghc/ticket/10607)