# derive-topdown

Derive type class instances

https://github.com/HaskellZhangSong/derive-topdown#readme

LTS Haskell 22.30: | 0.0.3.0 |

Stackage Nightly 2024-07-24: | 0.1.0.0 |

Latest on Hackage: | 0.1.0.0 |

**Song Zhang**

**Song Zhang**

`derive-topdown-0.1.0.0@sha256:04c7327d06318a88ec676aa2fbac22de5393d442910d3c2f00e02d8d0010263e,2791`

#### Module documentation for 0.1.0.0

*(full list with versions)*:

# 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.

```
{-# 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:

```
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.

```
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:

```
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`

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:

```
data A = A
deriving_superclasses ''Ord ''A
```

You wil get:

```
deriving_superclasses ''Ord ''A
======>
deriving instance Ord A
deriving instance Eq A
```

Mutual recursive type decalrations need to derive superclass together as the following:

```
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

## 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`

. 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`

## Changes

# derive-topdown

## derive-topdown-0.1.0.0

`0.1.0.0`

- Almost a reimplementation the deriving and instance generation functions.
- Implement class context generation. Now only necessary context type will be generated.
- This version only compatible for ghc-8.6 to ghc-9.10. ghc-8.4 and ghc-8.2 can build but not able to run test cases.

## derive-topdown-0.0.3.0

`0.0.3.0`

- Adapt to GHC 9.0.

## derive-topdown-0.0.2.1

`0.0.2.1`

- Remove unnecessary dependencies for testing.

## 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`

- Imporve error message.Will print the types list when type is not data or newtype defined.

## derive-topdown-0.0.0.9

`0.0.0.9`

- Changed API for
`strategy_derivng(s)`

. Deriving strategy should be specified first as the default grammar of`deriving`

. - Provided
`deriving_with_breaks`

function so that one can specify the types that prevent further standalone deriving declarations from generating process. This is mainly for`Generic`

class. See the test of deriving`Generic`

for`HsModule`

. - Fixed Strategy deriving problem. Deriving with NewtypeStrategy on data type defined by
`data`

keyword will be ignored. - Fixed problem with class context generation for phantom types. Phantom types will not be in the context now.
- Fixed
`ArrowT`

problem. It should be not a type variable and should appear in the context. - Handled data constructor which contains explicit
`forall`

. - Added test. It generates class instances for data types in
`template-haskell`

and`haskell-src`

.

- Changed API for

## derive-topdown-0.0.0.7

`0.0.0.7`

is a more carefully implemented version of derive-topdown. All APIs are**totally**changed compared with 0.0.0.2. Originally it did not work with types that contain type synonyms and polymorphic types. It can work for most common cases in this version now.

## derive-topdown-0.0.0.2

- Fixed some cabal file and API problems.

## derive-topdown-0.0.0.1

- This is only an experimental implementation for deriving class instances from top to bottom. There is a lot of deficiencies.