generic-deriving 1.5.0 → 1.14.7
raw patch · 34 files changed
Files
- CHANGELOG.md +235/−0
- LICENSE +28/−28
- README.md +86/−0
- Setup.hs +6/−6
- examples/Examples.hs +0/−583
- generic-deriving.cabal +150/−56
- src/Generics/Deriving.hs +24/−20
- src/Generics/Deriving/Base.hs +7/−165
- src/Generics/Deriving/ConNames.hs +63/−50
- src/Generics/Deriving/Copoint.hs +141/−0
- src/Generics/Deriving/Default.hs +271/−0
- src/Generics/Deriving/Enum.hs +1041/−210
- src/Generics/Deriving/Eq.hs +557/−93
- src/Generics/Deriving/Foldable.hs +274/−175
- src/Generics/Deriving/Functor.hs +182/−70
- src/Generics/Deriving/Instances.hs +106/−134
- src/Generics/Deriving/Monoid.hs +17/−217
- src/Generics/Deriving/Monoid/Internal.hs +239/−0
- src/Generics/Deriving/Semigroup.hs +12/−0
- src/Generics/Deriving/Semigroup/Internal.hs +167/−0
- src/Generics/Deriving/Show.hs +606/−142
- src/Generics/Deriving/TH.hs +1206/−415
- src/Generics/Deriving/TH/Internal.hs +830/−0
- src/Generics/Deriving/TH/Post4_9.hs +137/−0
- src/Generics/Deriving/Traversable.hs +184/−82
- src/Generics/Deriving/Uniplate.hs +345/−355
- tests/DefaultSpec.hs +161/−0
- tests/EmptyCaseSpec.hs +20/−0
- tests/ExampleSpec.hs +393/−0
- tests/Spec.hs +1/−0
- tests/T68Spec.hs +19/−0
- tests/T80Spec.hs +18/−0
- tests/T82Spec.hs +27/−0
- tests/TypeInTypeSpec.hs +52/−0
+ CHANGELOG.md view
@@ -0,0 +1,235 @@+# 1.14.7 [2026.01.03]+* Allow building with GHC 9.14.+* Remove unused `ghc-prim` dependency.++# 1.14.6 [2024.12.05]+* Drop support for GHC 7.10 and earlier.++# 1.14.5 [2023.08.06]+* Support building with `template-haskell-2.21.*` (GHC 9.8).+* The Template Haskell machinery now uses `TemplateHaskellQuotes` when+ building with GHC 8.0+ instead of manually constructing each Template Haskell+ `Name`. A consequence of this is that `generic-deriving` will now build with+ GHC 9.8, as `TemplateHaskellQuotes` abstracts over some internal Template+ Haskell changes introduced in 9.8.++# 1.14.4 [2023.04.30]+* Allow building with GHC backends where `HTYPE_SIG_ATOMIC_T` is not defined,+ such as the WASM backend.+* Place `INLINE [1]` pragmas on `from` and `to` implementations when types+ don't have too many constructors or fields, following the heuristics that GHC+ 9.2+ uses for `Generic` deriving.++# 1.14.3 [2023.02.27]+* Support `th-abstraction-0.5.*`.++# 1.14.2 [2022.07.23]+* Fix a bug in which `deriveAll1` could generate ill kinded code when using+ `kindSigOptions=False`, or when using GHC 8.0 or earlier.+* Fix a bug in which `deriveAll1` would reject data types whose last type+ variable has a kind besides `Type` or `k` on GHC 8.2 or later.++# 1.14.1 [2021.08.30]+* Backport the `Generic(1)` instances introduced for tuples (8 through 15) in+ `base-4.16`.+* Make the test suite compile on GHC 9.2 or later.+* Always import `Data.List` qualified to fix the build with recent GHCs.++# 1.14 [2020.09.30]+* Remove instances for `Data.Semigroup.Option`, which is deprecated as of+ `base-4.15.0.0`.+* Allow building with `template-haskell-2.17.0.0` (GHC 9.0).+* Fix a bug in which `deriveAll1` would needlessly reject data types whose last+ type parameter appears as an oversaturated argument to a type family.++# 1.13.1 [2019.11.26]+* Backport the `Generic(1)` instances for `Kleisli` introduced in `base-4.14`.++# 1.13 [2019.08.27]+* Make `GSemigroup` a superclass of `GMonoid`. Similarly, make+ `GSemigroup'` a superclass of `GMonoid'`.+* In the instance `GMonoid (Maybe a)`, relax the constraint on `a` from+ `GMonoid` to `GSemigroup`.++# 1.12.4 [2019.04.26]+* Support `th-abstraction-0.3.0.0` or later.++# 1.12.3 [2019.02.09]+* Support `template-haskell-2.15`.+* Add a `gshowList` method to `GShow`, which lets us avoid the need for+ `OverlappingInstances` in `Generics.Deriving.TH`. As a consequence, the+ `GShow String` instance has been removed, as it is now fully subsumed by+ the `GShow [a]` instance (with which it previously overlapped).+* Functions in `Generics.Deriving.TH` now balance groups of `(:*:)` and `(:+:)`+ as much as possible (`deriving Generic` was already performing this+ optimization, and now `generic-deriving` does too).+* Add a `Generics.Deriving.Default` module demonstrating and explaining+ how and why to use `DerivingVia`. There is also a test suite with+ further examples.++# 1.12.2 [2018.06.28]+* Backport the `Generic(1)` instances for `Data.Ord.Down`, introduced in+ `base-4.12`. Add `GEq`, `GShow`, `GSemigroup`, `GMonoid`, `GFunctor`,+ `GFoldable`, `GTraversable`, and `GCopoint` instances for `Down`.+* Refactor internals using `th-abstraction`.+* Adapt to `Maybe` moving to `GHC.Maybe` in GHC 8.6.++# 1.12.1 [2018.01.11]+* Remove a test that won't work on GHC 8.4.++# 1.12 [2017.12.07]+* Adapt to the `EmptyDataDeriving` proposal (introduced in GHC 8.4):+ * `Generics.Deriving.TH` now derives `to(1)` and `from(1)` implementations+ for empty data types that are strict in the argument.+ * Introduce an `EmptyCaseOptions` field to `Options` in+ `Generics.Deriving.TH`, which controls whether generated `from(1)`/`to(1)`+ implementations for empty data types should use the `EmptyCase` extension+ or not (as is the case in GHC 8.4).+ * Add `mkFrom0Options`, `mkFrom1Options`, `mkTo0Options`, and `mkTo1Options`+ functions to `Generics.Deriving.TH`, which take `EmptyCaseOptions` as+ arguments.+ * The backported instances for `V1` are now maximally lazy, as per+ `EmptyDataDeriving`. (Previously, some instances would unnecessarily force+ their argument, such as the `Eq` and `Ord` instances.)+ * Add instances for `V1` in `Generics.Deriving.Copoint`, `.Eq`, `.Foldable`,+ `.Functor`, `.Show`, and `.Traversable`.+* Remove the bitrotting `simplInstance` function from `Generics.Deriving.TH`.++# 1.11.2 [2017.04.10]+* Add `GEq`, `GShow`, `GEnum`, and `GIx` instances for the new data types+ in `Foreign.C.Types` (`CBool`) and `System.Posix.Types` (`CBlkSize`,+ `CBlkCnt`, `CClockId`, `CFsBlkCnt`, `CFsFilCnt`, `CId`, `CKey`, and `CTimer`)+ introduced in `base-4.10.0.0`++# 1.11.1 [2016.09.10]+* Fix Template Haskell regression involving data families+* Convert examples to test suite+* Backport missing `Data` and `Typeable` instances for `Rec1`, `M1`, `(:*:)`,+ `(:+:)`, and `(:.:)`++# 1.11+* The behavior of functions in `Generics.Deriving.TH` have changed with respect+ to when type synonyms are generated for `Rep(1)` definitions. In particular:++ * By default, `deriveRepresentable(1)` will no longer define its `Rep(1)`+ type family instance in terms of the type synonym that has to be generated+ with `deriveRep(1)`. Similarly, `deriveAll(1)` and `deriveAll0And1` will no+ longer generate a type synonym. Instead, they will generate `Generic(1)`+ instances that directly define the `Rep(1)` instance inline. If you wish+ to revert to the old behavior, you will need to use the variants of those+ functions suffixed with `-Options`.+ * New functions `makeRep0Inline` and `makeRep1Inline` have been added which,+ for most purposes, should replace uses of `makeRep0`/`makeRep0FromType`+ and `makeRep1`/`makeRep1FromType` (but see the next bullet point for a+ caveat).+ * The use of `deriveRep(1)`, `makeRep0`/`makeRep0FromType`, and+ `makeRep1`/`makeRep1FromType` are now discouraged, but those functions are+ still available. The reason is that on GHC 7.0/7.2/7.4, it is impossible to use+ `makeRep0Inline`/`makeRep1Inline` due to a GHC bug. Therefore, you must use+ `makeRep0`/`makeRep1` and `deriveRep(1)` on GHC 7.0/7.2/7.4 out of necessity.++ These changes make dealing with `Generic` instances that involve `PolyKinds`+ and `TypeInType` much easier.+* All functions suffixed in `-WithKindSigs` in `Generics.Deriving.TH` have been+ removed in favor of a more sensible `-Options` suffixing scheme. The ability to+ toggle whether explicit kind signatures are used on type variable binders has+ been folded into `KindSigOptions`, which is an explicit argument to+ `deriveRep0Options`/`deriveRep1Options` and also a field in the more general+ 'Options' data type.+* Furthermore, the behavior of derived instances' kind signatures has changed.+ By default, the TH code will now _always_ use explicit kind signatures+ whenever possible, regardless of whether you're working with plain data types+ or data family instances. This makes working with `TypeInType` less+ surprising, but at the cost of making it slightly more awkward to work with+ derived `Generic1` instances that constrain kinds to `*` by means of `(:.:)`.+* Since `Generic1` is polykinded on GHC 8.2 and later, the functions in+ `Generics.Deriving.TH` will no longer unify the kind of the last type+ parameter to be `*`.+* Fix a bug in which `makeRep` (and similarly named functions) would not check+ whether the argument type can actually have a well kinded `Generic(1)`+ instance.+* Backport missing `Foldable` and `Traversable` instances for `Rec1`++# 1.10.7+* Renamed internal modules to avoid using apostrophes (averting this bug:+ https://github.com/haskell/cabal/issues/3631)++# 1.10.6+* A new `base-4-9` Cabal flag was added to more easily facilitate installing+ `generic-deriving` with manually installed versions of `template-haskell`.++# 1.10.5+* Apply an optimization to generated `to(1)`/`from(1)` instances that factors out+ common occurrences of `M1`. See+ http://git.haskell.org/ghc.git/commit/9649fc0ae45e006c2ed54cc5ea2414158949fadb+* Export internal typeclass names+* Fix Haddock issues with GHC 7.8++# 1.10.4.1+* Fix Haddock parsing issue on GHC 8.0++# 1.10.4+* Backported `MonadPlus` and `MonadZip` instances for `U1`, and made the+ `Functor`, `Foldable`, `Traversable`, `Alternative`, and `Monad` instances+ for `U1` lazier to correspond with `base-4.9`++# 1.10.3+* Backported `Enum`, `Bounded`, `Ix`, `Functor`, `Applicative`, `Monad`,+ `MonadFix`, `MonadPlus`, `MonadZip`, `Foldable`, `Traversable`, and+ `Data` instances (introduced in `base-4.9`) for datatypes in the+ `Generics.Deriving.Base` module++# 1.10.2+* Fix TH regression on GHC 7.0++# 1.10.1+* Added `Generics.Deriving.Semigroup`+* Added `GMonoid` instance for `Data.Monoid.Alt`+* Fixed a bug in the `GEnum` instances for unsigned `Integral` types+* Added `Safe`/`Trustworthy` pragmas+* Made instances polykinded where possible++# 1.10.0+* On GHC 8.0 and up, `Generics.Deriving.TH` uses the new type literal-based+ machinery+* Rewrote the Template Haskell code to be robust. Among other things, this fixes+ a bug with deriving Generic1 instances on GHC 7.8, and makes it easier to+ derive Generic1 instances for datatypes that utilize GHC 8.0's `-XTypeInType`+ extension.+* Added `deriveAll0` and `makeRep0` for symmetry with `deriveAll1` and+ `makeRep1`+* Added`makeRep0FromType` and `makeRep1FromType` to make it easier to pass+ in the type instance (instead of having to pass each individual type+ variable, which can be error-prone)+* Added functions with the suffix `-WithKindSigs` to allow generating type+ synonyms with explicit kind signatures in the presence of kind-polymorphic+ type variables. This is necessary for some datatypes that use+ `-XTypeInType` to have derived `Generic(1)` instances, but is not turned on+ by default since the TH kind inference is not perfect and would cause+ otherwise valid code to be rejected. Use only if you know what you are doing.+* Fixed bug where a datatype with a single, nullary constructor would generate+ incorrect `Generic` instances+* More sensible `GEnum` instances for fixed-size integral types+* Added `GCopoint`, `GEnum`, `GEq`, `GFoldable`, `GFunctor`, `GMonoid`,+ `GShow`, and `GTraversable` instances for datatypes introduced in GHC 8.0+* Backported `Generic(1)` instances added in GHC 8.0. Specifically, `Generic`+ instances for `Complex` (`base-4.4` and later) `ExitCode`, and `Version`; and+ `Generic1` instances for `Complex` (`base-4.4` and later) and `Proxy`+ (`base-4.7` and later). Added `GEnum`, `GEq`, `GFoldable`, `GFunctor`, `GIx`,+ `GShow`, and `GTraversable` instances for these datatypes where appropriate.++# 1.9.0+* Allow deriving of Generic1 using Template Haskell+* Allow deriving of Generic(1) for data families+* Allow deriving of Generic(1) for constructor-less plain datatypes (but not+ data families, due to technical restrictions)+* Support for unboxed representation types on GHC 7.11++* More `GCopoint`, `GEnum`, `GEq`, `GFoldable`, `GFunctor`, `GIx`, `GMonoid`,+ `GShow`, and `GTraversable` instances+* The field accessors for the `(:+:)` type in `Generics.Deriving.Base` have+ been removed to be consistent with `GHC.Generics`+* Ensure that TH generates definitions for isNewtype and packageName, if a+ recent-enough version of GHC is used+* Ensure that TH-generated names are unique for a given data type's module and+ package (similar in spirit to Trac #10487)+* Allow building on stage-1 compilers
LICENSE view
@@ -1,28 +1,28 @@-Copyright (c) 2010 Universiteit Utrecht -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. 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. - -3. Neither the name of Universiteit Utrecht nor the names of its 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. - +Copyright (c) 2010 Universiteit Utrecht+All rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++2. 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.++3. Neither the name of Universiteit Utrecht nor the names of its 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,86 @@+## `generic-deriving`: Generic programming library for generalised deriving+[][Hackage: generic-deriving]+[](http://packdeps.haskellers.com/reverse/generic-deriving)+[][Haskell.org]+[][tl;dr Legal: BSD3]+[](https://github.com/dreixel/generic-deriving/actions?query=workflow%3AHaskell-CI)++[Hackage: generic-deriving]:+ http://hackage.haskell.org/package/generic-deriving+ "generic-deriving package on Hackage"+[Haskell.org]:+ http://www.haskell.org+ "The Haskell Programming Language"+[tl;dr Legal: BSD3]:+ https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29+ "BSD 3-Clause License (Revised)"++This package provides functionality for generalising the deriving mechanism+in Haskell to arbitrary classes. It was first described in the paper:++* [A generic deriving mechanism for Haskell](http://dreixel.net/research/pdf/gdmh.pdf).+ Jose Pedro Magalhaes, Atze Dijkstra, Johan Jeuring, and Andres Loeh. Haskell'10.++The current implementation integrates with the new GHC Generics. See+http://www.haskell.org/haskellwiki/GHC.Generics for more information.+Template Haskell code is provided for supporting older GHCs.++This library is organized as follows:++* `Generics.Deriving.Base` defines the core functionality for GHC generics,+ including the `Generic(1)` classes and representation data types.+ On modern versions of GHC, this simply re-exports `GHC.Generics` from+ `base`. On older versions of GHC, this module backports parts of+ `GHC.Generics` that were not included at the time, including `Generic(1)`+ instances.++* `Generics.Deriving.TH` implements Template Haskell functionality for+ deriving instances of `Generic(1)`.++* Educational code: in order to provide examples of how to define and use+ `GHC.Generics`-based defaults, this library offers a number of modules+ which define examples of type classes along with default implementations+ for the classes' methods. Currently, the following modules are provided:++ * `Generics.Deriving.Copoint`++ * `Generics.Deriving.ConNames`++ * `Generics.Deriving.Enum`++ * `Generics.Deriving.Eq`++ * `Generics.Deriving.Foldable`++ * `Generics.Deriving.Functor`++ * `Generics.Deriving.Monoid`++ * `Generics.Deriving.Semigroup`++ * `Generics.Deriving.Show`++ * `Generics.Deriving.Traversable`++ * `Generics.Deriving.Uniplate`++ It is worth emphasizing that these modules are primarly intended for+ educational purposes. Many of the classes in these modules resemble other+ commonly used classes—for example, `GShow` from `Generics.Deriving.Show`+ resembles `Show` from `base`—but in general, the classes that+ `generic-deriving` defines are not drop-in replacements. Moreover, the+ generic defaults that `generic-deriving` provide often make simplifying+ assumptions that may violate expectations of how these classes might work+ elsewhere. For example, the generic default for `GShow` does not behave+ exactly like `deriving Show` would.++ If you are seeking `GHC.Generics`-based defaults for type classes in+ `base`, consider using the+ [`generic-data`](http://hackage.haskell.org/package/generic-data) library.++* `Generics.Deriving.Default` provides newtypes that allow leveraging the+ generic defaults in this library using the `DerivingVia` GHC language+ extension.++* `Generics.Deriving` re-exports `Generics.Deriving.Base`,+ `Generics.Deriving.Default`, and a selection of educational modules.
Setup.hs view
@@ -1,6 +1,6 @@-module Main (main) where - -import Distribution.Simple - -main :: IO () -main = defaultMain +module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
− examples/Examples.hs
@@ -1,583 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE DatatypeContexts #-} -{-# LANGUAGE DeriveFunctor #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DeriveGeneric #-} -#endif - -module Main ( - -- * Run all tests - main - ) where - -import Prelude hiding (Either(..)) -import Generics.Deriving -import Generics.Deriving.TH - - --------------------------------------------------------------------------------- --- Temporary tests for TH generation --------------------------------------------------------------------------------- - -data (:/:) f a = MyType1Nil - | MyType1Cons { myType1Rec :: (f :/: a), myType2Rec :: MyType2 } - | MyType1Cons2 (f :/: a) Int a (f a) - -#if __GLASGOW_HASKELL__ >= 701 - deriving Generic -#endif - -data MyType2 = MyType2 Float ([] :/: Int) - -#if __GLASGOW_HASKELL__ < 701 - -$(deriveAll ''(:/:)) -$(deriveAll ''MyType2) - -#else - --- deriving instance Generic (f :/: a) -deriving instance Generic MyType2 - -#endif - --------------------------------------------------------------------------------- --- Example: Haskell's lists and Maybe --------------------------------------------------------------------------------- - -hList1, hList2 :: [Int] -hList1 = [1..10] -hList2 = [2,4..] - -maybe1 = Nothing -maybe2 = Just (Just 'p') - -double :: [Int] -> [Int] -double [] = [] -double (x:xs) = x:x:xs - -testsStandard = [ gshow hList1 - , gshow (children maybe2) - , gshow (transform (const "abc") []) - , gshow (transform double hList1) - , gshow (geq hList1 hList1) - , gshow (geq maybe1 maybe2) - , gshow (take 5 (genum :: [Maybe Int])) - , gshow (take 15 (genum :: [[Int]])) - , gshow (range ([0], [1::Int])) - , gshow (inRange ([0], [3,5::Int]) hList1) ] - --------------------------------------------------------------------------------- --- Example: trees of integers (kind *) --------------------------------------------------------------------------------- - -data Tree = Empty | Branch Int Tree Tree - -#if __GLASGOW_HASKELL__ >= 701 - -deriving instance Generic Tree - -instance GShow Tree -instance Uniplate Tree -instance GEnum Tree - -#else - -$(deriveAll ''Tree) - -instance GShow Tree where gshowsPrec = gshowsPrecdefault -instance Uniplate Tree where - children = childrendefault - context = contextdefault - descend = descenddefault - descendM = descendMdefault - transform = transformdefault - transformM = transformdefault -instance GEnum Tree where genum = genumDefault - -#endif - -upgradeTree :: Tree -> Tree -upgradeTree Empty = Branch 0 Empty Empty -upgradeTree (Branch n l r) = Branch (succ n) l r - --- Example usage -tree = Branch 2 Empty (Branch 1 Empty Empty) -testsTree = [ gshow tree - , gshow (children tree) - , gshow (descend (descend (\_ -> Branch 0 Empty Empty)) tree) - , gshow (context tree [Branch 1 Empty Empty,Empty]) - , gshow (transform upgradeTree tree) - , gshow (take 10 (genum :: [Tree])) ] - --------------------------------------------------------------------------------- --- Example: lists (kind * -> *) --------------------------------------------------------------------------------- - -data List a = Nil | Cons a (List a) - -#if __GLASGOW_HASKELL__ >= 701 -deriving instance Generic (List a) -#else - -type Rep0List_ a = D1 List_ ((:+:) (C1 Nil_ U1) (C1 Cons_ ((:*:) (Par0 a) (Rec0 (List a))))) -instance Generic (List a) where - type Rep (List a) = Rep0List_ a - from Nil = M1 (L1 (M1 U1)) - from (Cons h t) = M1 (R1 (M1 ((:*:) (K1 h) (K1 t)))) - to (M1 (L1 (M1 U1))) = Nil - to (M1 (R1 (M1 (K1 h :*: K1 t)))) = Cons h t - -#endif - -#if __GLASGOW_HASKELL__ >= 705 -deriving instance Generic1 List -#else - -data List_ -data Nil_ -data Cons_ - -instance Datatype List_ where - datatypeName _ = "List" - moduleName _ = "Examples" - -instance Constructor Nil_ where conName _ = "Nil" -instance Constructor Cons_ where conName _ = "Cons" - -type Rep1List_ = D1 List_ ((:+:) (C1 Nil_ U1) (C1 Cons_ ((:*:) Par1 (Rec1 List)))) -instance Generic1 List where - type Rep1 List = Rep1List_ - from1 Nil = M1 (L1 (M1 U1)) - from1 (Cons h t) = M1 (R1 (M1 (Par1 h :*: Rec1 t))) - to1 (M1 (L1 (M1 U1))) = Nil - to1 (M1 (R1 (M1 (Par1 h :*: Rec1 t)))) = Cons h t - -#endif - -#if __GLASGOW_HASKELL__ < 701 --- Instance for generic functions (should be automatically generated) -instance GFunctor List where - gmap = gmapdefault - -instance (GShow a) => GShow (List a) where - gshowsPrec = gshowsPrecdefault - -instance (Uniplate a) => Uniplate (List a) where - children = childrendefault - context = contextdefault - descend = descenddefault - descendM = descendMdefault - transform = transformdefault - transformM = transformdefault - -#else - -instance GFunctor List -instance (GShow a) => GShow (List a) -instance (Uniplate a) => Uniplate (List a) - -#endif - --- Example usage -list = Cons 'p' (Cons 'q' Nil) -listlist = Cons list (Cons Nil Nil) -- ["pq",""] - -testsList = [ gshow (gmap fromEnum list) - , gshow (gmap gshow listlist) - , gshow list - , gshow listlist - , gshow (children list) - , gshow (children listlist) ] - - --------------------------------------------------------------------------------- --- Example: Nested datatype, record selectors --------------------------------------------------------------------------------- - -data Nested a = Leaf | Nested { value :: a, rec :: Nested [a] } - deriving Functor - -#if __GLASGOW_HASKELL__ >= 701 -deriving instance Generic (Nested a) -#endif - -#if __GLASGOW_HASKELL__ < 705 -$(deriveMeta ''Nested) -#endif - -#if __GLASGOW_HASKELL__ < 701 -$(deriveRepresentable0 ''Nested) -#endif - -#if __GLASGOW_HASKELL__ >= 705 -deriving instance Generic1 Nested -#else - -type RepNested = D1 Nested_ (C1 Nested_Leaf_ U1 :+: C1 Nested_Nested_ (Par1 :*: Nested :.: Rec1 [])) -instance Generic1 Nested where - type Rep1 Nested = RepNested - from1 Leaf = M1 (L1 (M1 U1)) - from1 (Nested a l) = M1 (R1 (M1 (Par1 a :*: Comp1 (gmap Rec1 l)))) - to1 (M1 (L1 (M1 U1))) = Leaf - to1 (M1 (R1 (M1 (Par1 a :*: Comp1 l)))) = Nested a (gmap unRec1 l) -#endif - -#if __GLASGOW_HASKELL__ < 701 --- Instance for gshow (should be automatically generated) -instance (GShow a) => GShow (Nested a) where - gshowsPrec = gshowsPrecdefault - -instance GFunctor Nested where - gmap = gmapdefault - -#else - -instance (GShow a) => GShow (Nested a) -instance GFunctor Nested - -#endif - --- Example usage -nested :: Nested Int -nested = Nested 1 (Nested [2] (Nested [[3],[4,5],[]] Leaf)) ---nested = Nested 1 (Nested (Nested 1 Leaf) Leaf) - - -testsNested = [ gshow nested - , gshow (gmap gshow nested) ] - --------------------------------------------------------------------------------- --- Example: Type composition --------------------------------------------------------------------------------- - -data Rose a = Rose [a] [Rose a] - -#if __GLASGOW_HASKELL__ >= 701 -deriving instance Generic (Rose a) -#else - -type Rep0Rose a = D1 RoseD (C1 RoseC (Rec0 [a] :*: Rec0 [Rose a])) -instance Generic (Rose a) where - type Rep (Rose a) = Rep0Rose a - from (Rose a x) = M1 (M1 (K1 a :*: K1 x)) - to (M1 (M1 (K1 a :*: K1 x))) = Rose a x - -#endif - -#if __GLASGOW_HASKELL__ >= 705 -deriving instance Generic1 Rose -#else - -data RoseD -data RoseC - -instance Datatype RoseD where - datatypeName _ = "Rose" - moduleName _ = "Examples" - -instance Constructor RoseC where conName _ = "Rose" - --- Generic1 instances -type RepRose = D1 RoseD (C1 RoseC (Rec1 [] :*: [] :.: Rec1 Rose)) -instance Generic1 Rose where - type Rep1 Rose = RepRose - from1 (Rose a x) = M1 (M1 (Rec1 a :*: Comp1 (gmap Rec1 x))) - to1 (M1 (M1 (Rec1 a :*: Comp1 x))) = Rose a (gmap unRec1 x) - -#endif - -#if __GLASGOW_HASKELL_ >= 701 - -instance (GShow a) => GShow (Rose a) -instance GFunctor Rose - -#else - --- Instance for gshow (should be automatically generated) -instance (GShow a) => GShow (Rose a) where - gshowsPrec = gshowsPrecdefault - -instance GFunctor Rose where - gmap = gmapdefault - -#endif - --- Example usage -rose1 :: Rose Int -rose1 = Rose [1,2] [Rose [3,4] [], Rose [5] []] - -testsRose = [ gshow rose1 - , gshow (gmap gshow rose1) ] - --------------------------------------------------------------------------------- --- Example: Higher-order kinded datatype, type composition --------------------------------------------------------------------------------- - -data GRose f a = GRose (f a) (f (GRose f a)) - -deriving instance (Functor f) => Functor (GRose f) - -#if __GLASGOW_HASKELL__ >= 701 -deriving instance Generic (GRose f a) -#endif - -#if __GLASGOW_HASKELL__ < 705 -$(deriveMeta ''GRose) -#endif - -#if __GLASGOW_HASKELL__ < 701 -$(deriveRepresentable0 ''GRose) -#endif - -#if __GLASGOW_HASKELL__ >= 705 -deriving instance (Functor f) => Generic1 (GRose f) -#else - -type Rep1GRose f = D1 GRose_ (C1 GRose_GRose_ (Rec1 f :*: f :.: (Rec1 (GRose f)))) -instance (GFunctor f) => Generic1 (GRose f) where - type Rep1 (GRose f) = Rep1GRose f - from1 (GRose a x) = M1 (M1 (Rec1 a :*: Comp1 (gmap Rec1 x))) - to1 (M1 (M1 (Rec1 a :*: Comp1 x))) = GRose a (gmap unRec1 x) -#endif - -#if __GLASGOW_HASKELL__ < 701 --- Requires UndecidableInstances -instance (GShow (f a), GShow (f (GRose f a))) => GShow (GRose f a) where - gshowsPrec = gshowsPrecdefault - -instance (GFunctor f) => GFunctor (GRose f) where - gmap = gmapdefault - -#else - -instance (GShow (f a), GShow (f (GRose f a))) => GShow (GRose f a) -instance (Functor f, GFunctor f) => GFunctor (GRose f) - -#endif - --- Example usage -grose1 :: GRose [] Int -grose1 = GRose [1,2] [GRose [3] [], GRose [] []] - -testsGRose = [ gshow grose1 - , gshow (gmap gshow grose1) ] - --------------------------------------------------------------------------------- --- Example: NGRose (minimal) --------------------------------------------------------------------------------- - --- Cannot represent because of nesting on an argument other than the parameter -{- -data NGRose f a = NGNode a (f (NGRose (Comp f f) a)) -data Comp f g a = Comp (f (g a)) - -type Rep0NGRose f a = Par0 a :*: Rec0 (f (NGRose (Comp f f) a)) -instance Generic (NGRose f a) (Rep0NGRose f a) where - from (NGNode a x) = K1 a :*: K1 x - to (K1 a :*: K1 x) = NGNode a x - -type Rep0Comp f g a = Rec0 (f (g a)) -instance Generic (Comp f g a) (Rep0Comp f g a) where - from (Comp x) = K1 x - to (K1 x) = Comp x - -type Rep1Comp f g = f :.: Rec1 g -instance (GFunctor f) => Generic1 (Comp f g) (Rep1Comp f g) where - from1 (Comp x) = Comp1 (gmap Rec1 x) - to1 (Comp1 x) = Comp (gmap unRec1 x) - -type Rep1NGRose f = Par1 :*: f :.: Rec1 (NGRose (Comp f f)) -instance (GFunctor f) => Generic1 (NGRose f) (Rep1NGRose f) where - from1 (NGNode a x) = Par1 a :*: (Comp1 (gmap Rec1 x)) - to1 (Par1 a :*: Comp1 x) = NGNode a (gmap unRec1 x) - -instance (GShow a, GShow (f (NGRose (Comp f f) a))) => GShow (NGRose f a) where - gshowsPrec = t undefined where - t :: (GShow a, GShow (f (NGRose (Comp f f) a))) => Rep0NGRose f a x -> NGRose f a -> ShowS - t = gshowsPrecdefault - -instance (GShow a) => GShow (Comp f g a) where - gshowsPrec = t undefined where - t :: (GShow a) => Rep0Comp f g a x -> Comp f g a -> ShowS - t = gshowsPrecdefault - -instance (GFunctor f, GFunctor (Comp f f)) => GFunctor (NGRose f) where - gmap = t undefined where - t :: (GFunctor f, GFunctor (Comp f f)) => Rep1NGRose f a -> (a -> b) -> NGRose f a -> NGRose f b - t = gmapdefault - -ngrose1 :: NGRose [] Int -ngrose1 = NGNode 0 [ngrose2, ngrose2] - -ngrose2 :: NGRose (Comp [] []) Int -ngrose2 = NGNode 1 (Comp []) - -testsNGRose = [ gshow ngrose1 - , gshow (gmap gshow ngrose1) ] --} - --------------------------------------------------------------------------------- --- Example: Double type composition (minimal) --------------------------------------------------------------------------------- - --- Add this to EHC -unComp (Comp1 x) = x - -data Weird a = Weird [[[a]]] deriving Show - -type Rep1Weird = [] :.: [] :.: Rec1 [] -instance Generic1 Weird where - type Rep1 Weird = Rep1Weird - from1 (Weird x) = Comp1 (gmap (Comp1 . gmap Rec1) x) - to1 (Comp1 x) = Weird (gmap (gmap unRec1 . unComp) x) - -#if __GLASGOW_HASKELL__ >= 701 - -instance GFunctor Weird - -#else - -instance GFunctor Weird where - gmap = gmapdefault - -#endif - --------------------------------------------------------------------------------- --- Example: Nested datatype Bush (minimal) --------------------------------------------------------------------------------- - -data Bush a = BushNil | BushCons a (Bush (Bush a)) deriving Functor - -#if __GLASGOW_HASKELL__ >= 701 -deriving instance Generic (Bush a) -#endif - -#if __GLASGOW_HASKELL__ < 705 -$(deriveMeta ''Bush) -#endif - -#if __GLASGOW_HASKELL__ < 701 -$(deriveRepresentable0 ''Bush) -#endif - -#if __GLASGOW_HASKELL__ >= 705 -deriving instance Generic1 Bush -#else - -type Rep1Bush = U1 :+: Par1 :*: Bush :.: Rec1 Bush -instance Generic1 Bush where - type Rep1 Bush = Rep1Bush - from1 BushNil = L1 U1 - from1 (BushCons a b) = R1 (Par1 a :*: Comp1 (gmap Rec1 b)) - to1 (L1 U1) = BushNil - to1 (R1 (Par1 a :*: Comp1 b)) = BushCons a (gmap unRec1 b) - -#endif - -#if __GLASGOW_HASKELL__ < 701 - -instance GFunctor Bush where - gmap = gmapdefault - -instance (GShow a) => GShow (Bush a) where - gshowsPrec = gshowsPrecdefault - -#else - -instance GFunctor Bush -instance (GShow a) => GShow (Bush a) - -#endif - --- Example usage -bush1 :: Bush Int -bush1 = BushCons 0 (BushCons (BushCons 1 BushNil) BushNil) - -testsBush = [ gshow bush1 - , gshow (gmap gshow bush1) ] - --------------------------------------------------------------------------------- --- Example: Two parameters, datatype constraint, nested on other parameter --------------------------------------------------------------------------------- - --- Any constraints on |b| mean we cannot generate the Generic1 instance --- Constraints on |a| are just propagated to Generic and generic --- function instances -data (Show a) => Either a b = Left (Either [a] b) | Right b - - --- Generic1 instances -type Rep0Either a b = Rec0 (Either [a] b) :+: Rec0 b -instance (Show a) => Generic (Either a b) where - type Rep (Either a b) = Rep0Either a b - from (Left a) = L1 (K1 a) - from (Right a) = R1 (K1 a) - to (L1 (K1 a)) = Left a - to (R1 (K1 a)) = Right a - -type RepEither a = Rec1 (Either [a]) :+: Par1 -instance (Show a) => Generic1 (Either a) where - type Rep1 (Either a) = RepEither a - from1 (Left a) = L1 (Rec1 a) - from1 (Right a) = R1 (Par1 a) - to1 (L1 (Rec1 a)) = Left a - to1 (R1 (Par1 a)) = Right a - - -#if __GLASGOW_HASKELL__ < 701 --- Instance for gshow (should be automatically generated) -instance (Show a, GShow a, GShow b) => GShow (Either a b) where - gshowsPrec = gshowsPrecdefault - -instance (Show a) => GFunctor (Either a) where - gmap = gmapdefault - -#else - -instance (Show a, GShow a, GShow b) => GShow (Either a b) -instance (Show a) => GFunctor (Either a) - -#endif - -either1 :: Either Int Char -either1 = Left either2 - -either2 :: Either [Int] Char -either2 = Right 'p' - -testsEither = [ gshow either1 - , gshow (gmap gshow either1) ] - --------------------------------------------------------------------------------- --- Main tests --------------------------------------------------------------------------------- - -main :: IO () -main = do - let p = putStrLn . ((++) "- ") . show - putStrLn "[] and Maybe tests:" - mapM_ p testsStandard - putStrLn "Tests for Tree:" - mapM_ p testsTree - putStrLn "\nTests for List:" - mapM_ p testsList - putStrLn "\nTests for Rose:" - mapM_ p testsRose - putStrLn "\nTests for GRose:" - mapM_ p testsGRose - putStrLn "\nTests for Either:" - mapM_ p testsEither - putStrLn "\nTests for Nested:" - mapM_ p testsNested - putStrLn "\nTests for Bush:" - mapM_ p testsBush
generic-deriving.cabal view
@@ -1,56 +1,150 @@-name: generic-deriving -version: 1.5.0 -synopsis: Generic programming library for generalised deriving. -description: - - This package provides functionality for generalising the deriving mechanism - in Haskell to arbitrary classes. It was first described in the paper: - . - * /A generic deriving mechanism for Haskell/. - Jose Pedro Magalhaes, Atze Dijkstra, Johan Jeuring, and Andres Loeh. - Haskell'10. - . - The current implementation integrates with the new GHC Generics. See - <http://www.haskell.org/haskellwiki/GHC.Generics> for more information. - Template Haskell code is provided for supporting GHC before version 7.2. - -category: Generics -copyright: 2011-2013 Universiteit Utrecht, University of Oxford -license: BSD3 -license-file: LICENSE -author: José Pedro Magalhães -maintainer: generics@haskell.org -stability: experimental -build-type: Simple -cabal-version: >= 1.6 -tested-with: GHC == 7.0.3, GHC == 7.2.1, GHC == 7.4.1, GHC == 7.6.1 -extra-source-files: examples/Examples.hs - -source-repository head - type: git - location: https://github.com/dreixel/generic-deriving - -library - hs-source-dirs: src - exposed-modules: Generics.Deriving - Generics.Deriving.Base - Generics.Deriving.Instances - - Generics.Deriving.ConNames - Generics.Deriving.Enum - Generics.Deriving.Eq - Generics.Deriving.Foldable - Generics.Deriving.Functor - Generics.Deriving.Monoid - Generics.Deriving.Show - Generics.Deriving.Traversable - Generics.Deriving.Uniplate - - Generics.Deriving.TH - - build-depends: base < 5, template-haskell >=2.4 && <2.10 - if impl(ghc > 7.0) - build-depends: ghc-prim < 1 - - extensions: CPP - ghc-options: -Wall +name: generic-deriving+version: 1.14.7+synopsis: Generic programming library for generalised deriving.+description:++ This package provides functionality for generalising the deriving mechanism+ in Haskell to arbitrary classes. It was first described in the paper:+ .+ * /A generic deriving mechanism for Haskell/.+ Jose Pedro Magalhaes, Atze Dijkstra, Johan Jeuring, and Andres Loeh.+ Haskell'10.+ .+ The current implementation integrates with the new GHC Generics. See+ <http://www.haskell.org/haskellwiki/GHC.Generics> for more information.+ Template Haskell code is provided for supporting older GHCs.+ .+ This library is organized as follows:+ .+ * "Generics.Deriving.Base" defines the core functionality for GHC generics,+ including the @Generic(1)@ classes and representation data types.+ On modern versions of GHC, this simply re-exports "GHC.Generics" from+ @base@. On older versions of GHC, this module backports parts of+ "GHC.Generics" that were not included at the time, including @Generic(1)@+ instances.+ .+ * "Generics.Deriving.TH" implements Template Haskell functionality for+ deriving instances of @Generic(1)@.+ .+ * Educational code: in order to provide examples of how to define and use+ "GHC.Generics"-based defaults, this library offers a number of modules+ which define examples of type classes along with default implementations+ for the classes' methods. Currently, the following modules are provided:+ "Generics.Deriving.Copoint", "Generics.Deriving.ConNames",+ "Generics.Deriving.Enum", "Generics.Deriving.Eq",+ "Generics.Deriving.Foldable", "Generics.Deriving.Functor",+ "Generics.Deriving.Monoid", "Generics.Deriving.Semigroup",+ "Generics.Deriving.Show", "Generics.Deriving.Traversable",+ and "Generics.Deriving.Uniplate".+ .+ It is worth emphasizing that these modules are primarly intended for+ educational purposes. Many of the classes in these modules resemble other+ commonly used classes—for example, @GShow@ from "Generics.Deriving.Show"+ resembles @Show@ from @base@—but in general, the classes that+ @generic-deriving@ defines are not drop-in replacements. Moreover, the+ generic defaults that @generic-deriving@ provide often make simplifying+ assumptions that may violate expectations of how these classes might work+ elsewhere. For example, the generic default for @GShow@ does not behave+ exactly like @deriving Show@ would.+ .+ If you are seeking "GHC.Generics"-based defaults for type classes in+ @base@, consider using the+ @<http://hackage.haskell.org/package/generic-data generic-data>@ library.+ .+ * "Generics.Deriving.Default" provides newtypes that allow leveraging the+ generic defaults in this library using the @DerivingVia@ GHC language+ extension.+ .+ * "Generics.Deriving" re-exports "Generics.Deriving.Base",+ "Generics.Deriving.Default", and a selection of educational modules.++homepage: https://github.com/dreixel/generic-deriving+bug-reports: https://github.com/dreixel/generic-deriving/issues+category: Generics+copyright: 2011-2013 Universiteit Utrecht, University of Oxford+license: BSD3+license-file: LICENSE+author: José Pedro Magalhães+maintainer: generics@haskell.org+stability: experimental+build-type: Simple+cabal-version: >= 1.10+tested-with:+ GHC == 8.0.2+ , GHC == 8.2.2+ , GHC == 8.4.4+ , GHC == 8.6.5+ , GHC == 8.8.4+ , GHC == 8.10.7+ , GHC == 9.0.2+ , GHC == 9.2.8+ , GHC == 9.4.8+ , GHC == 9.6.6+ , GHC == 9.8.4+ , GHC == 9.10.3+ , GHC == 9.12.2+ , GHC == 9.14.1++extra-source-files: CHANGELOG.md+ , README.md++source-repository head+ type: git+ location: https://github.com/dreixel/generic-deriving++library+ hs-source-dirs: src+ exposed-modules: Generics.Deriving+ Generics.Deriving.Base+ Generics.Deriving.Instances+ Generics.Deriving.Copoint+ Generics.Deriving.ConNames+ Generics.Deriving.Default+ Generics.Deriving.Enum+ Generics.Deriving.Eq+ Generics.Deriving.Foldable+ Generics.Deriving.Functor+ Generics.Deriving.Monoid+ Generics.Deriving.Semigroup+ Generics.Deriving.Show+ Generics.Deriving.Traversable+ Generics.Deriving.Uniplate++ Generics.Deriving.TH++ other-modules: Generics.Deriving.Monoid.Internal+ Generics.Deriving.Semigroup.Internal+ Generics.Deriving.TH.Internal+ Generics.Deriving.TH.Post4_9+ Paths_generic_deriving++ build-depends: base >= 4.9 && < 5+ , containers >= 0.1 && < 0.9+ , template-haskell >= 2.11 && < 2.25+ -- TODO: Eventually, we should bump the lower version+ -- bounds to >=0.6 so that we can remove some CPP in+ -- Generics.Deriving.TH.Internal.+ , th-abstraction >= 0.4 && < 0.8++ default-language: Haskell2010+ ghc-options: -Wall++test-suite spec+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules: DefaultSpec+ EmptyCaseSpec+ ExampleSpec+ T68Spec+ T80Spec+ T82Spec+ TypeInTypeSpec+ build-depends: base+ , generic-deriving+ , hspec >= 2 && < 3+ build-tool-depends: hspec-discover:hspec-discover+ hs-source-dirs: tests+ default-language: Haskell2010+ ghc-options: -Wall -threaded -rtsopts+ if impl(ghc >= 8.6)+ ghc-options: -Wno-star-is-type
src/Generics/Deriving.hs view
@@ -1,20 +1,24 @@- -module Generics.Deriving ( - - module Generics.Deriving.Base, - module Generics.Deriving.ConNames, - module Generics.Deriving.Enum, - module Generics.Deriving.Eq, - module Generics.Deriving.Functor, - module Generics.Deriving.Show, - module Generics.Deriving.Uniplate - - ) where - -import Generics.Deriving.Base -import Generics.Deriving.ConNames -import Generics.Deriving.Enum -import Generics.Deriving.Eq -import Generics.Deriving.Functor -import Generics.Deriving.Show -import Generics.Deriving.Uniplate ++module Generics.Deriving (++ module Generics.Deriving.Base,+ module Generics.Deriving.Copoint,+ module Generics.Deriving.ConNames,+ module Generics.Deriving.Default,+ module Generics.Deriving.Enum,+ module Generics.Deriving.Eq,+ module Generics.Deriving.Functor,+ module Generics.Deriving.Show,+ module Generics.Deriving.Uniplate++ ) where++import Generics.Deriving.Base+import Generics.Deriving.Copoint+import Generics.Deriving.ConNames+import Generics.Deriving.Default+import Generics.Deriving.Enum+import Generics.Deriving.Eq+import Generics.Deriving.Functor+import Generics.Deriving.Show+import Generics.Deriving.Uniplate
src/Generics/Deriving/Base.hs view
@@ -1,165 +1,7 @@-{-# LANGUAGE EmptyDataDecls #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE CPP #-} - -module Generics.Deriving.Base ( -#if __GLASGOW_HASKELL__ < 701 - -- * Generic representation types - V1, U1(..), Par1(..), Rec1(..), K1(..), M1(..) - , (:+:)(..), (:*:)(..), (:.:)(..) - - -- ** Synonyms for convenience - , Rec0, Par0, R, P - , D1, C1, S1, D, C, S - - -- * Meta-information - , Datatype(..), Constructor(..), Selector(..), NoSelector - , Fixity(..), Associativity(..), Arity(..), prec - - -- * Generic type classes - , Generic(..), Generic1(..) - - , -#else - module GHC.Generics, -#endif - - ) where - - -#if __GLASGOW_HASKELL__ >= 701 -import GHC.Generics - -#else --------------------------------------------------------------------------------- --- Representation types --------------------------------------------------------------------------------- - --- | Void: used for datatypes without constructors -data V1 p - --- | Unit: used for constructors without arguments -data U1 p = U1 - --- | Used for marking occurrences of the parameter -newtype Par1 p = Par1 { unPar1 :: p } - - --- | Recursive calls of kind * -> * -newtype Rec1 f p = Rec1 { unRec1 :: f p } - --- | Constants, additional parameters and recursion of kind * -newtype K1 i c p = K1 { unK1 :: c } - --- | Meta-information (constructor names, etc.) -newtype M1 i c f p = M1 { unM1 :: f p } - --- | Sums: encode choice between constructors -infixr 5 :+: -data (:+:) f g p = L1 { unL1 :: f p } | R1 { unR1 :: g p } - --- | Products: encode multiple arguments to constructors -infixr 6 :*: -data (:*:) f g p = f p :*: g p - --- | Composition of functors -infixr 7 :.: -newtype (:.:) f g p = Comp1 { unComp1 :: f (g p) } - --- | Tag for K1: recursion (of kind *) -data R --- | Tag for K1: parameters (other than the last) -data P - --- | Type synonym for encoding recursion (of kind *) -type Rec0 = K1 R --- | Type synonym for encoding parameters (other than the last) -type Par0 = K1 P - --- | Tag for M1: datatype -data D --- | Tag for M1: constructor -data C --- | Tag for M1: record selector -data S - --- | Type synonym for encoding meta-information for datatypes -type D1 = M1 D - --- | Type synonym for encoding meta-information for constructors -type C1 = M1 C - --- | Type synonym for encoding meta-information for record selectors -type S1 = M1 S - --- | Class for datatypes that represent datatypes -class Datatype d where - -- | The name of the datatype, fully qualified - datatypeName :: t d (f :: * -> *) a -> String - moduleName :: t d (f :: * -> *) a -> String - --- | Class for datatypes that represent records -class Selector s where - -- | The name of the selector - selName :: t s (f :: * -> *) a -> String - --- | Used for constructor fields without a name -data NoSelector - -instance Selector NoSelector where selName _ = "" - --- | Class for datatypes that represent data constructors -class Constructor c where - -- | The name of the constructor - conName :: t c (f :: * -> *) a -> String - - -- | The fixity of the constructor - conFixity :: t c (f :: * -> *) a -> Fixity - conFixity = const Prefix - - -- | Marks if this constructor is a record - conIsRecord :: t c (f :: * -> *) a -> Bool - conIsRecord = const False - - --- | Datatype to represent the arity of a tuple. -data Arity = NoArity | Arity Int - deriving (Eq, Show, Ord, Read) - --- | Datatype to represent the fixity of a constructor. An infix --- | declaration directly corresponds to an application of 'Infix'. -data Fixity = Prefix | Infix Associativity Int - deriving (Eq, Show, Ord, Read) - --- | Get the precedence of a fixity value. -prec :: Fixity -> Int -prec Prefix = 10 -prec (Infix _ n) = n - --- | Datatype to represent the associativy of a constructor -data Associativity = LeftAssociative - | RightAssociative - | NotAssociative - deriving (Eq, Show, Ord, Read) - --- | Representable types of kind * -class Generic a where - type Rep a :: * -> * - -- | Convert from the datatype to its representation - from :: a -> Rep a x - -- | Convert from the representation to the datatype - to :: Rep a x -> a - --- | Representable types of kind * -> * -class Generic1 f where - type Rep1 f :: * -> * - -- | Convert from the datatype to its representation - from1 :: f a -> Rep1 f a - -- | Convert from the representation to the datatype - to1 :: Rep1 f a -> f a - -#endif +{-# LANGUAGE Safe #-}++module Generics.Deriving.Base (module GHC.Generics) where++import GHC.Generics++import Generics.Deriving.Instances ()
src/Generics/Deriving/ConNames.hs view
@@ -1,50 +1,63 @@-{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeSynonymInstances #-} - ------------------------------------------------------------------------------ --- | --- Module : Generics.Deriving.ConNames --- Copyright : (c) 2012 University of Oxford --- License : BSD3 --- --- Maintainer : generics@haskell.org --- Stability : experimental --- Portability : non-portable --- --- Summary: Return the name of all the constructors of a type. --- ------------------------------------------------------------------------------ - -module Generics.Deriving.ConNames ( - - -- * Functionality for retrieving the names of all the possible contructors - -- of a type - ConNames(..), conNames - - ) where - -import Generics.Deriving.Base - - -class ConNames f where - gconNames :: f a -> [String] - -instance (ConNames f, ConNames g) => ConNames (f :+: g) where - gconNames (_ :: (f :+: g) a) = gconNames (undefined :: f a) ++ - gconNames (undefined :: g a) - -instance (ConNames f) => ConNames (D1 c f) where - gconNames (_ :: (D1 c f) a) = gconNames (undefined :: f a) - -instance (Constructor c) => ConNames (C1 c f) where - gconNames x = [conName x] - --- We should never need any other instances. - - --- | Return the name of all the constructors of the type of the given term. -conNames :: (Generic a, ConNames (Rep a)) => a -> [String] -conNames x = gconNames (undefined `asTypeOf` (from x)) +{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++{- |+Module : Generics.Deriving.ConNames+Copyright : (c) 2012 University of Oxford+License : BSD3++Maintainer : generics@haskell.org+Stability : experimental+Portability : non-portable++Summary: Return the name of all the constructors of a type.+-}++module Generics.Deriving.ConNames (++ -- * Functionality for retrieving the names of the possible contructors+ -- of a type or the constructor name of a given value+ ConNames(..), conNames, conNameOf++ ) where++import Generics.Deriving.Base+++class ConNames f where+ gconNames :: f a -> [String]+ gconNameOf :: f a -> String++instance (ConNames f, ConNames g) => ConNames (f :+: g) where+ gconNames (_ :: (f :+: g) a) = gconNames (undefined :: f a) +++ gconNames (undefined :: g a)++ gconNameOf (L1 x) = gconNameOf x+ gconNameOf (R1 x) = gconNameOf x++instance (ConNames f) => ConNames (D1 c f) where+ gconNames (_ :: (D1 c f) a) = gconNames (undefined :: f a)++ gconNameOf (M1 x) = gconNameOf x++instance (Constructor c) => ConNames (C1 c f) where+ gconNames x = [conName x]++ gconNameOf x = conName x+++-- We should never need any other instances.+++-- | Return the name of all the constructors of the type of the given term.+conNames :: (Generic a, ConNames (Rep a)) => a -> [String]+conNames x = gconNames (undefined `asTypeOf` (from x))++-- | Return the name of the constructor of the given term+conNameOf :: (ConNames (Rep a), Generic a) => a -> String+conNameOf x = gconNameOf (from x)
+ src/Generics/Deriving/Copoint.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}++module Generics.Deriving.Copoint (+ -- * GCopoint class+ GCopoint(..)++ -- * Default method+ , gcopointdefault++ -- * Internal class+ , GCopoint'(..)++ ) where++import Control.Applicative (WrappedMonad)++import Data.Functor.Identity (Identity)+import qualified Data.Functor.Sum as Functor (Sum)+import Data.Monoid (Alt, Dual)+import qualified Data.Monoid as Monoid (Sum)+import Data.Ord (Down)+import Data.Semigroup (Arg, First, Last, Max, Min, WrappedMonoid)++import Generics.Deriving.Base++--------------------------------------------------------------------------------+-- Generic copoint+--------------------------------------------------------------------------------++-- General copoint may return 'Nothing'++class GCopoint' t where+ gcopoint' :: t a -> Maybe a++instance GCopoint' V1 where+ gcopoint' _ = Nothing++instance GCopoint' U1 where+ gcopoint' U1 = Nothing++instance GCopoint' Par1 where+ gcopoint' (Par1 a) = Just a++instance GCopoint' (K1 i c) where+ gcopoint' _ = Nothing++instance GCopoint' f => GCopoint' (M1 i c f) where+ gcopoint' (M1 a) = gcopoint' a++instance (GCopoint' f, GCopoint' g) => GCopoint' (f :+: g) where+ gcopoint' (L1 a) = gcopoint' a+ gcopoint' (R1 a) = gcopoint' a++-- Favours left "hole" for copoint+instance (GCopoint' f, GCopoint' g) => GCopoint' (f :*: g) where+ gcopoint' (a :*: b) = case (gcopoint' a) of+ Just x -> Just x+ Nothing -> gcopoint' b++instance (GCopoint f) => GCopoint' (Rec1 f) where+ gcopoint' (Rec1 a) = Just $ gcopoint a++instance (GCopoint f, GCopoint' g) => GCopoint' (f :.: g) where+ gcopoint' (Comp1 x) = gcopoint' . gcopoint $ x++class GCopoint d where+ gcopoint :: d a -> a+ default gcopoint :: (Generic1 d, GCopoint' (Rep1 d))+ => (d a -> a)+ gcopoint = gcopointdefault++gcopointdefault :: (Generic1 d, GCopoint' (Rep1 d))+ => d a -> a+gcopointdefault x = case (gcopoint' . from1 $ x) of+ Just x' -> x'+ Nothing -> error "Data type is not copointed"++-- instance (Generic1 d, GCopoint' (Rep1 d)) => GCopoint d++-- Base types instances+instance GCopoint ((,) a) where+ gcopoint = gcopointdefault++instance GCopoint ((,,) a b) where+ gcopoint = gcopointdefault++instance GCopoint ((,,,) a b c) where+ gcopoint = gcopointdefault++instance GCopoint ((,,,,) a b c d) where+ gcopoint = gcopointdefault++instance GCopoint ((,,,,,) a b c d e) where+ gcopoint = gcopointdefault++instance GCopoint ((,,,,,,) a b c d e f) where+ gcopoint = gcopointdefault++instance GCopoint f => GCopoint (Alt f) where+ gcopoint = gcopointdefault++instance GCopoint (Arg a) where+ gcopoint = gcopointdefault++instance GCopoint Down where+ gcopoint = gcopointdefault++instance GCopoint Dual where+ gcopoint = gcopointdefault++instance GCopoint First where+ gcopoint = gcopointdefault++instance GCopoint Identity where+ gcopoint = gcopointdefault++instance GCopoint Last where+ gcopoint = gcopointdefault++instance GCopoint Max where+ gcopoint = gcopointdefault++instance GCopoint Min where+ gcopoint = gcopointdefault++instance (GCopoint f, GCopoint g) => GCopoint (Functor.Sum f g) where+ gcopoint = gcopointdefault++instance GCopoint Monoid.Sum where+ gcopoint = gcopointdefault++instance GCopoint m => GCopoint (WrappedMonad m) where+ gcopoint = gcopointdefault++instance GCopoint WrappedMonoid where+ gcopoint = gcopointdefault
+ src/Generics/Deriving/Default.hs view
@@ -0,0 +1,271 @@+-- |+-- Module : Generics.Deriving.Default+-- Description : Default implementations of generic classes+-- License : BSD-3-Clause+--+-- Maintainer : generics@haskell.org+-- Stability : experimental+-- Portability : non-portable+--+-- GHC 8.6 introduced the+-- @<https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html?highlight=derivingvia#extension-DerivingVia DerivingVia>@+-- language extension, which means a typeclass instance can be derived from+-- an existing instance for an isomorphic type. Any newtype is isomorphic+-- to the underlying type. By implementing a typeclass once for the newtype,+-- it is possible to derive any typeclass for any type with a 'Generic' instance.+--+-- For a number of classes, there are sensible default instantiations. In+-- older GHCs, these can be supplied in the class definition, using the+-- @<https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html?highlight=defaultsignatures#extension-DefaultSignatures DefaultSignatures>@+-- extension. However, only one default can be provided! With+-- @<https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html?highlight=derivingvia#extension-DerivingVia DerivingVia>@+-- it is now possible to choose from many+-- default instantiations.+--+-- This package contains a number of such classes. This module demonstrates+-- how one might create a family of newtypes ('Default', 'Default1') for+-- which such instances are defined.+--+-- One might then use+-- @<https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html?highlight=derivingvia#extension-DerivingVia DerivingVia>@+-- as follows. The implementations of the data types are elided here (they+-- are irrelevant). For most cases, either the deriving clause with the+-- data type definition or the standalone clause will work (for some types+-- it is necessary to supply the context explicitly using the latter form).+-- See the source of this module for the implementations of instances for+-- the 'Default' family of newtypes and the source of the test suite for+-- some types which derive instances via these wrappers.++{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE UndecidableInstances #-}++module Generics.Deriving.Default+ ( -- * Kind @*@ (aka @Type@)++ -- $default++ Default(..)++ , -- * Kind @* -> *@ (aka @Type -> Type@)++ -- $default1++ Default1(..)++ -- * Other kinds++ -- $other-kinds+ ) where++import Control.Monad (liftM)++import Generics.Deriving.Base+import Generics.Deriving.Copoint+import Generics.Deriving.Enum+import Generics.Deriving.Eq+import Generics.Deriving.Foldable+import Generics.Deriving.Functor+import Generics.Deriving.Monoid+import Generics.Deriving.Semigroup+import Generics.Deriving.Show+import Generics.Deriving.Traversable+import Generics.Deriving.Uniplate++-- $default+--+-- For classes which take an argument of kind 'Data.Kind.Type', use+-- 'Default'. An example of this class from @base@ would be 'Eq', or+-- 'Generic'.+--+-- These examples use 'GShow' and 'GEq'; they are interchangeable.+--+-- @+-- data MyType = …+-- deriving ('Generic')+-- deriving ('GEq') via ('Default' MyType)+--+-- deriving via ('Default' MyType) instance 'GShow' MyType+-- @+--+-- Instances may be parameterized by type variables.+--+-- @+-- data MyType1 a = …+-- deriving ('Generic')+-- deriving ('GShow') via ('Default' (MyType1 a))+--+-- deriving via 'Default' (MyType1 a) instance 'GEq' a => 'GEq' (MyType1 a)+-- @+--+-- These types both require instances for 'Generic'. This is because the+-- implementations of 'geq' and 'gshowsPrec' for @'Default' b@ have a @'Generic'+-- b@ constraint, i.e. the type corresponding to @b@ require a 'Generic'+-- instance. For these two types, that means instances for @'Generic' MyType@+-- and @'Generic' (MyType1 a)@ respectively.+--+-- It also means the 'Generic' instance is not needed when there is already+-- a generic instance for the type used to derive the relevant instances.+-- For an example, see the documentation of the 'GShow' instance for+-- 'Default', below.++-- | This newtype wrapper can be used to derive default instances for+-- classes taking an argument of kind 'Data.Kind.Type'.+newtype Default a = Default { unDefault :: a }++-- $default1+--+-- For classes which take an argument of kind @'Data.Kind.Type' ->+-- 'Data.Kind.Type'@, use 'Default1'. An example of this class from @base@+-- would be 'Data.Functor.Classes.Eq1', or 'Generic1'.+--+-- Unlike for @MyType1@, there can be no implementation of these classes for @MyType :: 'Data.Kind.Type'@.+--+-- @+-- data MyType1 a = …+-- deriving ('Generic1')+-- deriving ('GFunctor') via ('Default1' MyType1)+--+-- deriving via ('Default1' MyType1) instance 'GFoldable' MyType1+-- @+--+-- Note that these instances require a @'Generic1' MyType1@ constraint as+-- 'gmap' and 'gfoldMap' have @'Generic1' a@ constraints on the+-- implementations for @'Default1' a@.++-- | This newtype wrapper can be used to derive default instances for+-- classes taking an argument of kind @'Data.Kind.Type' -> 'Data.Kind.Type'@.+newtype Default1 f a = Default1 { unDefault1 :: f a }++-- $other-kinds+--+-- These principles extend to classes taking arguments of other kinds.++--------------------------------------------------------------------------------+-- Eq+--------------------------------------------------------------------------------++instance (Generic a, GEq' (Rep a)) => GEq (Default a) where+ -- geq :: Default a -> Default a -> Bool+ Default x `geq` Default y = x `geqdefault` y++--------------------------------------------------------------------------------+-- Enum+--------------------------------------------------------------------------------++-- | The 'Enum' class in @base@ is slightly different; it comprises 'toEnum' and+-- 'fromEnum'. "Generics.Deriving.Enum" provides functions 'toEnumDefault'+-- and 'fromEnumDefault'.+instance (Generic a, GEq a, Enum' (Rep a)) => GEnum (Default a) where+ -- genum :: [Default a]+ genum = Default . to <$> enum'++--------------------------------------------------------------------------------+-- Show+--------------------------------------------------------------------------------++-- | For example, with this type:+--+-- @+-- newtype TestShow = TestShow 'Bool'+-- deriving ('GShow') via ('Default' 'Bool')+-- @+--+-- 'gshow' for @TestShow@ would produce the same string as `gshow` for+-- 'Bool'.+--+-- In this example, @TestShow@ requires no 'Generic' instance, as the+-- constraint on 'gshowsPrec' from @'Default' 'Bool'@ is @'Generic' 'Bool'@.+--+-- In general, when using a newtype wrapper, the instance can be derived+-- via the wrapped type, as here (via @'Default' 'Bool'@ rather than @'Default'+-- TestShow@).+instance (Generic a, GShow' (Rep a)) => GShow (Default a) where+ -- gshowsPrec :: Int -> Default a -> ShowS+ gshowsPrec n (Default x) = gshowsPrecdefault n x++--------------------------------------------------------------------------------+-- Semigroup+--------------------------------------------------------------------------------++-- | Semigroups often have many sensible implementations of+-- 'Data.Semigroup.<>' / 'gsappend', and therefore no sensible default.+-- Indeed, there is no 'GSemigroup'' instance for representations of sum+-- types.+--+-- In other cases, one may wish to use the existing wrapper newtypes in+-- @base@, such as the following (using 'Data.Semigroup.First'):+--+-- @+-- newtype FirstSemigroup = FirstSemigroup 'Bool'+-- deriving stock ('Eq', 'Show')+-- deriving ('GSemigroup') via ('Data.Semigroup.First' 'Bool')+-- @+--+instance (Generic a, GSemigroup' (Rep a)) => GSemigroup (Default a) where+ -- gsappend :: Default a -> Default a -> Default a+ Default x `gsappend` Default y = Default $ x `gsappenddefault` y++--------------------------------------------------------------------------------+-- Monoid+--------------------------------------------------------------------------------++instance (Generic a, GMonoid' (Rep a)) => GMonoid (Default a) where+ -- gmempty :: Default a+ gmempty = Default gmemptydefault++ -- gmappend :: Default a -> Default a -> Default a+ Default x `gmappend` Default y = Default $ x `gmappenddefault` y++--------------------------------------------------------------------------------+-- Uniplate+--------------------------------------------------------------------------------++instance (Generic a, Uniplate' (Rep a) a, Context' (Rep a) a) => Uniplate (Default a) where++ -- children :: Default a -> [Default a]+ -- context :: Default a -> [Default a] -> Default a+ -- descend :: (Default a -> Default a) -> Default a -> Default a+ -- descendM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a)+ -- transform :: (Default a -> Default a) -> Default a -> Default a+ -- transformM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a)++ children (Default x) = Default <$> childrendefault x+ context (Default x) ys = Default $ contextdefault x (unDefault <$> ys)+ descend f (Default x) = Default $ descenddefault (unDefault . f . Default) x+ descendM f (Default x) = liftM Default $ descendMdefault (liftM unDefault . f . Default) x+ transform f (Default x) = Default $ transformdefault (unDefault . f . Default) x+ transformM f (Default x) = liftM Default $ transformMdefault (liftM unDefault . f . Default) x++--------------------------------------------------------------------------------+-- Functor+--------------------------------------------------------------------------------++instance (Generic1 f, GFunctor' (Rep1 f)) => GFunctor (Default1 f) where+ -- gmap :: (a -> b) -> (Default1 f) a -> (Default1 f) b+ gmap f (Default1 fx) = Default1 $ gmapdefault f fx++--------------------------------------------------+-- Copoint+--------------------------------------------------++instance (Generic1 f, GCopoint' (Rep1 f)) => GCopoint (Default1 f) where+ -- gcopoint :: Default1 f a -> a+ gcopoint = gcopointdefault . unDefault1++--------------------------------------------------+-- Foldable+--------------------------------------------------++instance (Generic1 t, GFoldable' (Rep1 t)) => GFoldable (Default1 t) where+ -- gfoldMap :: Monoid m => (a -> m) -> Default1 t a -> m+ gfoldMap f (Default1 tx) = gfoldMapdefault f tx++--------------------------------------------------+-- Traversable+--------------------------------------------------++instance (Generic1 t, GFunctor' (Rep1 t), GFoldable' (Rep1 t), GTraversable' (Rep1 t)) => GTraversable (Default1 t) where+ -- gtraverse :: Applicative f => (a -> f b) -> Default1 t a -> f (Default1 t b)+ gtraverse f (Default1 fx) = Default1 <$> gtraversedefault f fx
src/Generics/Deriving/Enum.hs view
@@ -1,210 +1,1041 @@-{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - -module Generics.Deriving.Enum ( - - -- * Generic enum class - GEnum(..) - - -- * Default definitions for GEnum - , genumDefault, toEnumDefault, fromEnumDefault - - -- * Generic Ix class - , GIx(..) - - -- * Default definitions for GIx - , rangeDefault, indexDefault, inRangeDefault - - ) where - - -import Generics.Deriving.Base -import Generics.Deriving.Instances () -import Generics.Deriving.Eq - - ------------------------------------------------------------------------------ --- Utility functions for Enum' ------------------------------------------------------------------------------ - -infixr 5 ||| - --- | Interleave elements from two lists. Similar to (++), but swap left and --- right arguments on every recursive application. --- --- From Mark Jones' talk at AFP2008 -(|||) :: [a] -> [a] -> [a] -[] ||| ys = ys -(x:xs) ||| ys = x : ys ||| xs - --- | Diagonalization of nested lists. Ensure that some elements from every --- sublist will be included. Handles infinite sublists. --- --- From Mark Jones' talk at AFP2008 -diag :: [[a]] -> [a] -diag = concat . foldr skew [] . map (map (\x -> [x])) - -skew :: [[a]] -> [[a]] -> [[a]] -skew [] ys = ys -skew (x:xs) ys = x : combine (++) xs ys - -combine :: (a -> a -> a) -> [a] -> [a] -> [a] -combine _ xs [] = xs -combine _ [] ys = ys -combine f (x:xs) (y:ys) = f x y : combine f xs ys - -findIndex :: (a -> Bool) -> [a] -> Maybe Int -findIndex p xs = let l = [ i | (y,i) <- zip xs [(0::Int)..], p y] - in if (null l) - then Nothing - else Just (head l) - --------------------------------------------------------------------------------- --- Generic enum --------------------------------------------------------------------------------- - -class Enum' f where - enum' :: [f a] - -instance Enum' U1 where - enum' = [U1] - -instance (GEnum c) => Enum' (K1 i c) where - enum' = map K1 genum - -instance (Enum' f) => Enum' (M1 i c f) where - enum' = map M1 enum' - -instance (Enum' f, Enum' g) => Enum' (f :+: g) where - enum' = map L1 enum' ||| map R1 enum' - -instance (Enum' f, Enum' g) => Enum' (f :*: g) where - enum' = diag [ [ x :*: y | y <- enum' ] | x <- enum' ] - - -#if __GLASGOW_HASKELL__ < 701 - -instance (GEnum a) => GEnum (Maybe a) where - genum = genumDefault - -instance (GEnum a) => GEnum [a] where - genum = genumDefault - -#else - -instance (GEnum a) => GEnum (Maybe a) -instance (GEnum a) => GEnum [a] - -#endif - -genumDefault :: (Generic a, Enum' (Rep a)) => [a] -genumDefault = map to enum' - -toEnumDefault :: (Generic a, Enum' (Rep a)) => Int -> a -toEnumDefault i = let l = enum' - in if (length l > i) - then to (l !! i) - else error "toEnum: invalid index" - -fromEnumDefault :: (GEq a, Generic a, Enum' (Rep a)) - => a -> Int -fromEnumDefault x = case findIndex (geq x) (map to enum') of - Nothing -> error "fromEnum: no corresponding index" - Just i -> i - - -class GEnum a where - genum :: [a] - -#if __GLASGOW_HASKELL__ >= 701 - default genum :: (Generic a, Enum' (Rep a)) => [a] - genum = genumDefault -#endif - -instance GEnum Int where - genum = [0..] ||| (neg 0) where - neg n = (n-1) : neg (n-1) - --------------------------------------------------------------------------------- --- Generic Ix --------------------------------------------------------------------------------- - --- Minimal complete instance: 'range', 'index' and 'inRange'. -class (Ord a) => GIx a where - -- | The list of values in the subrange defined by a bounding pair. - range :: (a,a) -> [a] - -- | The position of a subscript in the subrange. - index :: (a,a) -> a -> Int - -- | Returns 'True' the given subscript lies in the range defined - -- the bounding pair. - inRange :: (a,a) -> a -> Bool -#if __GLASGOW_HASKELL__ >= 701 - default range :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> [a] - range = rangeDefault - - default index :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> a -> Int - index = indexDefault - - default inRange :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> a -> Bool - inRange = inRangeDefault -#endif - -rangeDefault :: (GEq a, Generic a, Enum' (Rep a)) - => (a,a) -> [a] -rangeDefault = t (map to enum') where - t l (x,y) = - case (findIndex (geq x) l, findIndex (geq y) l) of - (Nothing, _) -> error "rangeDefault: no corresponding index" - (_, Nothing) -> error "rangeDefault: no corresponding index" - (Just i, Just j) -> take (j-i) (drop i l) - -indexDefault :: (GEq a, Generic a, Enum' (Rep a)) - => (a,a) -> a -> Int -indexDefault = t (map to enum') where - t l (x,y) z = - case (findIndex (geq x) l, findIndex (geq y) l) of - (Nothing, _) -> error "indexDefault: no corresponding index" - (_, Nothing) -> error "indexDefault: no corresponding index" - (Just i, Just j) -> case findIndex (geq z) (take (j-i) (drop i l)) of - Nothing -> error "indexDefault: index out of range" - Just k -> k - -inRangeDefault :: (GEq a, Generic a, Enum' (Rep a)) - => (a,a) -> a -> Bool -inRangeDefault = t (map to enum') where - t l (x,y) z = - case (findIndex (geq x) l, findIndex (geq y) l) of - (Nothing, _) -> error "indexDefault: no corresponding index" - (_, Nothing) -> error "indexDefault: no corresponding index" - (Just i, Just j) -> maybe False (const True) - (findIndex (geq z) (take (j-i) (drop i l))) - -#if __GLASGOW_HASKELL__ < 701 - -instance (GEq a, GEnum a, GIx a) => GIx (Maybe a) where - range = rangeDefault - index = indexDefault - inRange = inRangeDefault - -instance (GEq a, GEnum a, GIx a) => GIx [a] where - range = rangeDefault - index = indexDefault - inRange = inRangeDefault - -#else - -instance (GEq a, GEnum a, GIx a) => GIx (Maybe a) -instance (GEq a, GEnum a, GIx a) => GIx [a] - -#endif - -instance GIx Int where - range (m,n) = [m..n] - index (m,_n) i = i - m - inRange (m,n) i = m <= i && i <= n +{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++#include "HsBaseConfig.h"++module Generics.Deriving.Enum (++ -- * Generic enum class+ GEnum(..)++ -- * Default definitions for GEnum+ , genumDefault, toEnumDefault, fromEnumDefault++ -- * Internal enum class+ , Enum'(..)++ -- * Generic Ix class+ , GIx(..)++ -- * Default definitions for GIx+ , rangeDefault, indexDefault, inRangeDefault++ ) where++import Control.Applicative (Const, ZipList)++import Data.Coerce (coerce)+import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import Data.Int+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe (listToMaybe)+import Data.Monoid (All, Alt, Any, Dual, Product, Sum)+import qualified Data.Monoid as Monoid (First, Last)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg, Max, Min, WrappedMonoid)+import Data.Word++import Foreign.C.Types+import Foreign.Ptr++import Generics.Deriving.Base+import Generics.Deriving.Eq++import Numeric.Natural (Natural)++import System.Exit (ExitCode)+import System.Posix.Types++-----------------------------------------------------------------------------+-- Utility functions for Enum'+-----------------------------------------------------------------------------++infixr 5 |||++-- | Interleave elements from two lists. Similar to (++), but swap left and+-- right arguments on every recursive application.+--+-- From Mark Jones' talk at AFP2008+(|||) :: [a] -> [a] -> [a]+[] ||| ys = ys+(x:xs) ||| ys = x : ys ||| xs++-- | Diagonalization of nested lists. Ensure that some elements from every+-- sublist will be included. Handles infinite sublists.+--+-- From Mark Jones' talk at AFP2008+diag :: [[a]] -> [a]+diag = concat . foldr skew [] . map (map (\x -> [x]))++skew :: [[a]] -> [[a]] -> [[a]]+skew [] ys = ys+skew (x:xs) ys = x : combine (++) xs ys++combine :: (a -> a -> a) -> [a] -> [a] -> [a]+combine _ xs [] = xs+combine _ [] ys = ys+combine f (x:xs) (y:ys) = f x y : combine f xs ys++findIndex :: (a -> Bool) -> [a] -> Maybe Int+findIndex p xs = let l = [ i | (y,i) <- zip xs [(0::Int)..], p y]+ in listToMaybe l++--------------------------------------------------------------------------------+-- Generic enum+--------------------------------------------------------------------------------++class Enum' f where+ enum' :: [f a]++instance Enum' U1 where+ enum' = [U1]++instance (GEnum c) => Enum' (K1 i c) where+ enum' = map K1 genum++instance (Enum' f) => Enum' (M1 i c f) where+ enum' = map M1 enum'++instance (Enum' f, Enum' g) => Enum' (f :+: g) where+ enum' = map L1 enum' ||| map R1 enum'++instance (Enum' f, Enum' g) => Enum' (f :*: g) where+ enum' = diag [ [ x :*: y | y <- enum' ] | x <- enum' ]++genumDefault :: (Generic a, Enum' (Rep a)) => [a]+genumDefault = map to enum'++toEnumDefault :: (Generic a, Enum' (Rep a)) => Int -> a+toEnumDefault i = let l = enum'+ in if (length l > i)+ then to (l !! i)+ else error "toEnum: invalid index"++fromEnumDefault :: (GEq a, Generic a, Enum' (Rep a))+ => a -> Int+fromEnumDefault x = case findIndex (geq x) (map to enum') of+ Nothing -> error "fromEnum: no corresponding index"+ Just i -> i+++class GEnum a where+ genum :: [a]++ default genum :: (Generic a, Enum' (Rep a)) => [a]+ genum = genumDefault++genumNumUnbounded :: Num a => [a]+genumNumUnbounded = pos 0 ||| neg 0 where+ pos n = n : pos (n + 1)+ neg n = (n-1) : neg (n - 1)++genumNumSigned :: (Bounded a, Enum a, Num a) => [a]+genumNumSigned = [0 .. maxBound] ||| [-1, -2 .. minBound]++genumNumUnsigned :: (Enum a, Num a) => [a]+genumNumUnsigned = [0 ..]++-- Base types instances+instance GEnum () where+ genum = genumDefault++instance (GEnum a, GEnum b) => GEnum (a, b) where+ genum = genumDefault++instance (GEnum a, GEnum b, GEnum c) => GEnum (a, b, c) where+ genum = genumDefault++instance (GEnum a, GEnum b, GEnum c, GEnum d) => GEnum (a, b, c, d) where+ genum = genumDefault++instance (GEnum a, GEnum b, GEnum c, GEnum d, GEnum e) => GEnum (a, b, c, d, e) where+ genum = genumDefault++instance (GEnum a, GEnum b, GEnum c, GEnum d, GEnum e, GEnum f)+ => GEnum (a, b, c, d, e, f) where+ genum = genumDefault++instance (GEnum a, GEnum b, GEnum c, GEnum d, GEnum e, GEnum f, GEnum g)+ => GEnum (a, b, c, d, e, f, g) where+ genum = genumDefault++instance GEnum a => GEnum [a] where+ genum = genumDefault++instance (GEnum (f p), GEnum (g p)) => GEnum ((f :+: g) p) where+ genum = genumDefault++instance (GEnum (f p), GEnum (g p)) => GEnum ((f :*: g) p) where+ genum = genumDefault++instance GEnum (f (g p)) => GEnum ((f :.: g) p) where+ genum = genumDefault++instance GEnum All where+ genum = genumDefault++instance GEnum (f a) => GEnum (Alt f a) where+ genum = genumDefault++instance GEnum Any where+ genum = genumDefault++instance (GEnum a, GEnum b) => GEnum (Arg a b) where+ genum = genumDefault++instance GEnum Associativity where+ genum = genumDefault++instance GEnum Bool where+ genum = genumDefault++#if defined(HTYPE_CC_T)+instance GEnum CCc where+ genum = coerce (genum :: [HTYPE_CC_T])+#endif++instance GEnum CChar where+ genum = coerce (genum :: [HTYPE_CHAR])++instance GEnum CClock where+ genum = coerce (genum :: [HTYPE_CLOCK_T])++#if defined(HTYPE_DEV_T)+instance GEnum CDev where+ genum = coerce (genum :: [HTYPE_DEV_T])+#endif++instance GEnum CDouble where+ genum = coerce (genum :: [HTYPE_DOUBLE])++instance GEnum CFloat where+ genum = coerce (genum :: [HTYPE_FLOAT])++#if defined(HTYPE_GID_T)+instance GEnum CGid where+ genum = coerce (genum :: [HTYPE_GID_T])+#endif++#if defined(HTYPE_INO_T)+instance GEnum CIno where+ genum = coerce (genum :: [HTYPE_INO_T])+#endif++instance GEnum CInt where+ genum = coerce (genum :: [HTYPE_INT])++instance GEnum CIntMax where+ genum = coerce (genum :: [HTYPE_INTMAX_T])++instance GEnum CIntPtr where+ genum = coerce (genum :: [HTYPE_INTPTR_T])++instance GEnum CLLong where+ genum = coerce (genum :: [HTYPE_LONG_LONG])++instance GEnum CLong where+ genum = coerce (genum :: [HTYPE_LONG])++#if defined(HTYPE_MODE_T)+instance GEnum CMode where+ genum = coerce (genum :: [HTYPE_MODE_T])+#endif++#if defined(HTYPE_NLINK_T)+instance GEnum CNlink where+ genum = coerce (genum :: [HTYPE_NLINK_T])+#endif++#if defined(HTYPE_OFF_T)+instance GEnum COff where+ genum = coerce (genum :: [HTYPE_OFF_T])+#endif++instance GEnum a => GEnum (Complex a) where+ genum = genumDefault++instance GEnum a => GEnum (Const a b) where+ genum = genumDefault++#if defined(HTYPE_PID_T)+instance GEnum CPid where+ genum = coerce (genum :: [HTYPE_PID_T])+#endif++instance GEnum CPtrdiff where+ genum = coerce (genum :: [HTYPE_PTRDIFF_T])++#if defined(HTYPE_RLIM_T)+instance GEnum CRLim where+ genum = coerce (genum :: [HTYPE_RLIM_T])+#endif++instance GEnum CSChar where+ genum = coerce (genum :: [HTYPE_SIGNED_CHAR])++#if defined(HTYPE_SPEED_T)+instance GEnum CSpeed where+ genum = coerce (genum :: [HTYPE_SPEED_T])+#endif++instance GEnum CSUSeconds where+ genum = coerce (genum :: [HTYPE_SUSECONDS_T])++instance GEnum CShort where+ genum = coerce (genum :: [HTYPE_SHORT])++instance GEnum CSigAtomic where+#if defined(HTYPE_SIG_ATOMIC_T)+ genum = coerce (genum :: [HTYPE_SIG_ATOMIC_T])+#else+ genum = coerce (genum :: [Int32])+#endif++instance GEnum CSize where+ genum = coerce (genum :: [HTYPE_SIZE_T])++#if defined(HTYPE_SSIZE_T)+instance GEnum CSsize where+ genum = coerce (genum :: [HTYPE_SSIZE_T])+#endif++#if defined(HTYPE_TCFLAG_T)+instance GEnum CTcflag where+ genum = coerce (genum :: [HTYPE_TCFLAG_T])+#endif++instance GEnum CTime where+ genum = coerce (genum :: [HTYPE_TIME_T])++instance GEnum CUChar where+ genum = coerce (genum :: [HTYPE_UNSIGNED_CHAR])++#if defined(HTYPE_UID_T)+instance GEnum CUid where+ genum = coerce (genum :: [HTYPE_UID_T])+#endif++instance GEnum CUInt where+ genum = coerce (genum :: [HTYPE_UNSIGNED_INT])++instance GEnum CUIntMax where+ genum = coerce (genum :: [HTYPE_UINTMAX_T])++instance GEnum CUIntPtr where+ genum = coerce (genum :: [HTYPE_UINTPTR_T])++instance GEnum CULLong where+ genum = coerce (genum :: [HTYPE_UNSIGNED_LONG_LONG])++instance GEnum CULong where+ genum = coerce (genum :: [HTYPE_UNSIGNED_LONG])++instance GEnum CUSeconds where+ genum = coerce (genum :: [HTYPE_USECONDS_T])++instance GEnum CUShort where+ genum = coerce (genum :: [HTYPE_UNSIGNED_SHORT])++instance GEnum CWchar where+ genum = coerce (genum :: [HTYPE_WCHAR_T])++instance GEnum Double where+ genum = genumNumUnbounded++instance GEnum a => GEnum (Dual a) where+ genum = genumDefault++instance (GEnum a, GEnum b) => GEnum (Either a b) where+ genum = genumDefault++instance GEnum ExitCode where+ genum = genumDefault++instance GEnum Fd where+ genum = coerce (genum :: [CInt])++instance GEnum a => GEnum (Monoid.First a) where+ genum = genumDefault++instance GEnum a => GEnum (Semigroup.First a) where+ genum = genumDefault++instance GEnum Fixity where+ genum = genumDefault++instance GEnum Float where+ genum = genumNumUnbounded++instance GEnum a => GEnum (Identity a) where+ genum = genumDefault++instance GEnum Int where+ genum = genumNumSigned++instance GEnum Int8 where+ genum = genumNumSigned++instance GEnum Int16 where+ genum = genumNumSigned++instance GEnum Int32 where+ genum = genumNumSigned++instance GEnum Int64 where+ genum = genumNumSigned++instance GEnum Integer where+ genum = genumNumUnbounded++instance GEnum IntPtr where+ genum = genumNumSigned++instance GEnum c => GEnum (K1 i c p) where+ genum = genumDefault++instance GEnum a => GEnum (Monoid.Last a) where+ genum = genumDefault++instance GEnum a => GEnum (Semigroup.Last a) where+ genum = genumDefault++instance GEnum (f p) => GEnum (M1 i c f p) where+ genum = genumDefault++instance GEnum a => GEnum (Max a) where+ genum = genumDefault++instance GEnum a => GEnum (Maybe a) where+ genum = genumDefault++instance GEnum a => GEnum (Min a) where+ genum = genumDefault++instance GEnum Natural where+ genum = genumNumUnsigned++instance GEnum a => GEnum (NonEmpty a) where+ genum = genumDefault++instance GEnum Ordering where+ genum = genumDefault++instance GEnum p => GEnum (Par1 p) where+ genum = genumDefault++instance GEnum a => GEnum (Product a) where+ genum = genumDefault++instance GEnum (Proxy s) where+ genum = genumDefault++instance GEnum (f p) => GEnum (Rec1 f p) where+ genum = genumDefault++instance GEnum a => GEnum (Sum a) where+ genum = genumDefault++instance GEnum (U1 p) where+ genum = genumDefault++instance GEnum Word where+ genum = genumNumUnsigned++instance GEnum Word8 where+ genum = genumNumUnsigned++instance GEnum Word16 where+ genum = genumNumUnsigned++instance GEnum Word32 where+ genum = genumNumUnsigned++instance GEnum Word64 where+ genum = genumNumUnsigned++instance GEnum WordPtr where+ genum = genumNumUnsigned++instance GEnum m => GEnum (WrappedMonoid m) where+ genum = genumDefault++instance GEnum a => GEnum (ZipList a) where+ genum = genumDefault++#if MIN_VERSION_base(4,10,0)+instance GEnum CBool where+ genum = coerce (genum :: [HTYPE_BOOL])++# if defined(HTYPE_BLKSIZE_T)+instance GEnum CBlkSize where+ genum = coerce (genum :: [HTYPE_BLKSIZE_T])+# endif++# if defined(HTYPE_BLKCNT_T)+instance GEnum CBlkCnt where+ genum = coerce (genum :: [HTYPE_BLKCNT_T])+# endif++# if defined(HTYPE_CLOCKID_T)+instance GEnum CClockId where+ genum = coerce (genum :: [HTYPE_CLOCKID_T])+# endif++# if defined(HTYPE_FSBLKCNT_T)+instance GEnum CFsBlkCnt where+ genum = coerce (genum :: [HTYPE_FSBLKCNT_T])+# endif++# if defined(HTYPE_FSFILCNT_T)+instance GEnum CFsFilCnt where+ genum = coerce (genum :: [HTYPE_FSFILCNT_T])+# endif++# if defined(HTYPE_ID_T)+instance GEnum CId where+ genum = coerce (genum :: [HTYPE_ID_T])+# endif++# if defined(HTYPE_KEY_T)+instance GEnum CKey where+ genum = coerce (genum :: [HTYPE_KEY_T])+# endif+#endif++--------------------------------------------------------------------------------+-- Generic Ix+--------------------------------------------------------------------------------++-- Minimal complete instance: 'range', 'index' and 'inRange'.+class (Ord a) => GIx a where+ -- | The list of values in the subrange defined by a bounding pair.+ range :: (a,a) -> [a]+ -- | The position of a subscript in the subrange.+ index :: (a,a) -> a -> Int+ -- | Returns 'True' the given subscript lies in the range defined+ -- the bounding pair.+ inRange :: (a,a) -> a -> Bool++ default range :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> [a]+ range = rangeDefault++ default index :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> a -> Int+ index = indexDefault++ default inRange :: (GEq a, Generic a, Enum' (Rep a)) => (a,a) -> a -> Bool+ inRange = inRangeDefault++rangeDefault :: (GEq a, Generic a, Enum' (Rep a))+ => (a,a) -> [a]+rangeDefault = t (map to enum') where+ t l (x,y) =+ case (findIndex (geq x) l, findIndex (geq y) l) of+ (Nothing, _) -> error "rangeDefault: no corresponding index"+ (_, Nothing) -> error "rangeDefault: no corresponding index"+ (Just i, Just j) -> take (j-i) (drop i l)++indexDefault :: (GEq a, Generic a, Enum' (Rep a))+ => (a,a) -> a -> Int+indexDefault = t (map to enum') where+ t l (x,y) z =+ case (findIndex (geq x) l, findIndex (geq y) l) of+ (Nothing, _) -> error "indexDefault: no corresponding index"+ (_, Nothing) -> error "indexDefault: no corresponding index"+ (Just i, Just j) -> case findIndex (geq z) (take (j-i) (drop i l)) of+ Nothing -> error "indexDefault: index out of range"+ Just k -> k++inRangeDefault :: (GEq a, Generic a, Enum' (Rep a))+ => (a,a) -> a -> Bool+inRangeDefault = t (map to enum') where+ t l (x,y) z =+ case (findIndex (geq x) l, findIndex (geq y) l) of+ (Nothing, _) -> error "indexDefault: no corresponding index"+ (_, Nothing) -> error "indexDefault: no corresponding index"+ (Just i, Just j) -> maybe False (const True)+ (findIndex (geq z) (take (j-i) (drop i l)))++rangeEnum :: Enum a => (a, a) -> [a]+rangeEnum (m,n) = [m..n]++indexIntegral :: Integral a => (a, a) -> a -> Int+indexIntegral (m,_n) i = fromIntegral (i - m)++inRangeOrd :: Ord a => (a, a) -> a -> Bool+inRangeOrd (m,n) i = m <= i && i <= n++-- Base types instances+instance GIx () where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b) => GIx (a, b) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b, GEq c, GEnum c, GIx c)+ => GIx (a, b, c) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b, GEq c, GEnum c, GIx c,+ GEq d, GEnum d, GIx d)+ => GIx (a, b, c, d) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b, GEq c, GEnum c, GIx c,+ GEq d, GEnum d, GIx d, GEq e, GEnum e, GIx e)+ => GIx (a, b, c, d, e) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b, GEq c, GEnum c, GIx c,+ GEq d, GEnum d, GIx d, GEq e, GEnum e, GIx e, GEq f, GEnum f, GIx f)+ => GIx (a, b, c, d, e, f) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b, GEq c, GEnum c, GIx c,+ GEq d, GEnum d, GIx d, GEq e, GEnum e, GIx e, GEq f, GEnum f, GIx f,+ GEq g, GEnum g, GIx g)+ => GIx (a, b, c, d, e, f, g) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx [a] where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx All where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq (f a), GEnum (f a), GIx (f a)) => GIx (Alt f a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Any where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEnum b) => GIx (Arg a b) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Associativity where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Bool where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx CChar where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++#if defined(HTYPE_GID_T)+instance GIx CGid where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++#if defined(HTYPE_INO_T)+instance GIx CIno where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++instance GIx CInt where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CIntMax where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CIntPtr where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CLLong where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CLong where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++#if defined(HTYPE_MODE_T)+instance GIx CMode where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++#if defined(HTYPE_NLINK_T)+instance GIx CNlink where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++#if defined(HTYPE_OFF_T)+instance GIx COff where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++#if defined(HTYPE_PID_T)+instance GIx CPid where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++instance GIx CPtrdiff where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++#if defined(HTYPE_RLIM_T)+instance GIx CRLim where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++instance GIx CSChar where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CShort where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CSigAtomic where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CSize where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++#if defined(HTYPE_SSIZE_T)+instance GIx CSsize where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++#if defined(HTYPE_TCFLAG_T)+instance GIx CTcflag where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++instance GIx CUChar where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++#if defined(HTYPE_UID_T)+instance GIx CUid where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+#endif++instance GIx CUInt where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CUIntMax where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CUIntPtr where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CULLong where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CULong where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CUShort where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx CWchar where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance (GEq a, GEnum a, GIx a) => GIx (Dual a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a, GEq b, GEnum b, GIx b) => GIx (Either a b) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx ExitCode where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Fd where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance (GEq a, GEnum a, GIx a) => GIx (Monoid.First a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Semigroup.First a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Fixity where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Identity a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Int where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Int8 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Int16 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Int32 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Int64 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Integer where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx IntPtr where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance (GEq a, GEnum a, GIx a) => GIx (Monoid.Last a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Semigroup.Last a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Max a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Maybe a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Min a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Natural where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance (GEq a, GEnum a, GIx a) => GIx (NonEmpty a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Ordering where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Product a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx (Proxy s) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance (GEq a, GEnum a, GIx a) => GIx (Sum a) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++instance GIx Word where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Word8 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Word16 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Word32 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx Word64 where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance GIx WordPtr where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++instance (GEq m, GEnum m, GIx m) => GIx (WrappedMonoid m) where+ range = rangeDefault+ index = indexDefault+ inRange = inRangeDefault++#if MIN_VERSION_base(4,10,0)+instance GIx CBool where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd++# if defined(HTYPE_BLKSIZE_T)+instance GIx CBlkSize where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_BLKCNT_T)+instance GIx CBlkCnt where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_CLOCKID_T)+instance GIx CClockId where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_FSBLKCNT_T)+instance GIx CFsBlkCnt where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_FSFILCNT_T)+instance GIx CFsFilCnt where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_ID_T)+instance GIx CId where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif++# if defined(HTYPE_KEY_T)+instance GIx CKey where+ range = rangeEnum+ index = indexIntegral+ inRange = inRangeOrd+# endif+#endif
src/Generics/Deriving/Eq.hs view
@@ -1,93 +1,557 @@-{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE CPP #-} - -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - - -module Generics.Deriving.Eq ( - -- * Generic show class - GEq(..) - -#if __GLASGOW_HASKELL__ >= 701 --- Nothing -#else - -- * Default definition - , geqdefault -#endif - - ) where - - -import Generics.Deriving.Base -import Generics.Deriving.Instances () --- import GHC.Generics - --------------------------------------------------------------------------------- --- Generic show --------------------------------------------------------------------------------- - -class GEq' f where - geq' :: f a -> f a -> Bool - -instance GEq' U1 where - geq' _ _ = True - -instance (GEq c) => GEq' (K1 i c) where - geq' (K1 a) (K1 b) = geq a b - --- No instances for P or Rec because geq is only applicable to types of kind * - -instance (GEq' a) => GEq' (M1 i c a) where - geq' (M1 a) (M1 b) = geq' a b - -instance (GEq' a, GEq' b) => GEq' (a :+: b) where - geq' (L1 a) (L1 b) = geq' a b - geq' (R1 a) (R1 b) = geq' a b - geq' _ _ = False - -instance (GEq' a, GEq' b) => GEq' (a :*: b) where - geq' (a1 :*: b1) (a2 :*: b2) = geq' a1 a2 && geq' b1 b2 - - -class GEq a where - geq :: a -> a -> Bool - - -#if __GLASGOW_HASKELL__ >= 701 - default geq :: (Generic a, GEq' (Rep a)) => a -> a -> Bool - geq x y = geq' (from x) (from y) -#endif - -#if __GLASGOW_HASKELL__ >= 701 --- Nothing; the default is in the class -#else -geqdefault :: (Generic a, GEq' (Rep a)) => a -> a -> Bool -geqdefault x y = geq' (from x) (from y) -#endif - --- Base types instances -instance GEq Char where geq = (==) -instance GEq Int where geq = (==) -instance GEq Float where geq = (==) - - -#if __GLASGOW_HASKELL__ < 701 - -instance (GEq a) => GEq (Maybe a) where - geq = geqdefault - -instance (GEq a) => GEq [a] where - geq = geqdefault - -#else - -instance (GEq a) => GEq (Maybe a) -instance (GEq a) => GEq [a] - -#endif +{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE MagicHash #-}++#include "HsBaseConfig.h"++module Generics.Deriving.Eq (+ -- * Generic Eq class+ GEq(..)++ -- * Default definition+ , geqdefault++ -- * Internal Eq class+ , GEq'(..)++ ) where++import Control.Applicative (Const, ZipList)++import Data.Char (GeneralCategory)+import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import Data.Int+import Data.List.NonEmpty (NonEmpty)+import qualified Data.Monoid as Monoid (First, Last)+import Data.Monoid (All, Alt, Any, Dual, Product, Sum)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg(..), Max, Min, WrappedMonoid)+import Data.Version (Version)+import Data.Void (Void)+import Data.Word++import Foreign.C.Error+import Foreign.C.Types+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Ptr+import Foreign.StablePtr (StablePtr)++import Generics.Deriving.Base++import GHC.Exts hiding (Any)++import Numeric.Natural (Natural)++import System.Exit (ExitCode)+import System.IO (BufferMode, Handle, HandlePosn, IOMode, SeekMode)+import System.IO.Error (IOErrorType)+import System.Posix.Types++--------------------------------------------------------------------------------+-- Generic show+--------------------------------------------------------------------------------++class GEq' f where+ geq' :: f a -> f a -> Bool++instance GEq' V1 where+ geq' _ _ = True++instance GEq' U1 where+ geq' _ _ = True++instance (GEq c) => GEq' (K1 i c) where+ geq' (K1 a) (K1 b) = geq a b++-- No instances for P or Rec because geq is only applicable to types of kind *++instance (GEq' a) => GEq' (M1 i c a) where+ geq' (M1 a) (M1 b) = geq' a b++instance (GEq' a, GEq' b) => GEq' (a :+: b) where+ geq' (L1 a) (L1 b) = geq' a b+ geq' (R1 a) (R1 b) = geq' a b+ geq' _ _ = False++instance (GEq' a, GEq' b) => GEq' (a :*: b) where+ geq' (a1 :*: b1) (a2 :*: b2) = geq' a1 a2 && geq' b1 b2++-- Unboxed types+instance GEq' UAddr where+ geq' (UAddr a1) (UAddr a2) = isTrue# (eqAddr# a1 a2)+instance GEq' UChar where+ geq' (UChar c1) (UChar c2) = isTrue# (eqChar# c1 c2)+instance GEq' UDouble where+ geq' (UDouble d1) (UDouble d2) = isTrue# (d1 ==## d2)+instance GEq' UFloat where+ geq' (UFloat f1) (UFloat f2) = isTrue# (eqFloat# f1 f2)+instance GEq' UInt where+ geq' (UInt i1) (UInt i2) = isTrue# (i1 ==# i2)+instance GEq' UWord where+ geq' (UWord w1) (UWord w2) = isTrue# (eqWord# w1 w2)+++class GEq a where+ geq :: a -> a -> Bool++ default geq :: (Generic a, GEq' (Rep a)) => a -> a -> Bool+ geq = geqdefault++geqdefault :: (Generic a, GEq' (Rep a)) => a -> a -> Bool+geqdefault x y = geq' (from x) (from y)++-- Base types instances+instance GEq () where+ geq = geqdefault++instance (GEq a, GEq b) => GEq (a, b) where+ geq = geqdefault++instance (GEq a, GEq b, GEq c) => GEq (a, b, c) where+ geq = geqdefault++instance (GEq a, GEq b, GEq c, GEq d) => GEq (a, b, c, d) where+ geq = geqdefault++instance (GEq a, GEq b, GEq c, GEq d, GEq e) => GEq (a, b, c, d, e) where+ geq = geqdefault++instance (GEq a, GEq b, GEq c, GEq d, GEq e, GEq f)+ => GEq (a, b, c, d, e, f) where+ geq = geqdefault++instance (GEq a, GEq b, GEq c, GEq d, GEq e, GEq f, GEq g)+ => GEq (a, b, c, d, e, f, g) where+ geq = geqdefault++instance GEq a => GEq [a] where+ geq = geqdefault++instance (GEq (f p), GEq (g p)) => GEq ((f :+: g) p) where+ geq = geqdefault++instance (GEq (f p), GEq (g p)) => GEq ((f :*: g) p) where+ geq = geqdefault++instance GEq (f (g p)) => GEq ((f :.: g) p) where+ geq = geqdefault++instance GEq All where+ geq = geqdefault++instance GEq (f a) => GEq (Alt f a) where+ geq = geqdefault++instance GEq Any where+ geq = geqdefault++instance GEq a => GEq (Arg a b) where+ geq (Arg a _) (Arg b _) = geq a b++instance GEq Associativity where+ geq = geqdefault++instance GEq Bool where+ geq = geqdefault++instance GEq BufferMode where+ geq = (==)++#if defined(HTYPE_CC_T)+instance GEq CCc where+ geq = (==)+#endif++instance GEq CChar where+ geq = (==)++instance GEq CClock where+ geq = (==)++#if defined(HTYPE_DEV_T)+instance GEq CDev where+ geq = (==)+#endif++instance GEq CDouble where+ geq = (==)++instance GEq CFloat where+ geq = (==)++#if defined(HTYPE_GID_T)+instance GEq CGid where+ geq = (==)+#endif++instance GEq Char where+ geq = (==)++#if defined(HTYPE_INO_T)+instance GEq CIno where+ geq = (==)+#endif++instance GEq CInt where+ geq = (==)++instance GEq CIntMax where+ geq = (==)++instance GEq CIntPtr where+ geq = (==)++instance GEq CLLong where+ geq = (==)++instance GEq CLong where+ geq = (==)++#if defined(HTYPE_MODE_T)+instance GEq CMode where+ geq = (==)+#endif++#if defined(HTYPE_NLINK_T)+instance GEq CNlink where+ geq = (==)+#endif++#if defined(HTYPE_OFF_T)+instance GEq COff where+ geq = (==)+#endif++instance GEq a => GEq (Complex a) where+ geq = geqdefault++instance GEq a => GEq (Const a b) where+ geq = geqdefault++#if defined(HTYPE_PID_T)+instance GEq CPid where+ geq = (==)+#endif++instance GEq CPtrdiff where+ geq = (==)++#if defined(HTYPE_RLIM_T)+instance GEq CRLim where+ geq = (==)+#endif++instance GEq CSChar where+ geq = (==)++#if defined(HTYPE_SPEED_T)+instance GEq CSpeed where+ geq = (==)+#endif++instance GEq CSUSeconds where+ geq = (==)++instance GEq CShort where+ geq = (==)++instance GEq CSigAtomic where+ geq = (==)++instance GEq CSize where+ geq = (==)++#if defined(HTYPE_SSIZE_T)+instance GEq CSsize where+ geq = (==)+#endif++#if defined(HTYPE_TCFLAG_T)+instance GEq CTcflag where+ geq = (==)+#endif++instance GEq CTime where+ geq = (==)++instance GEq CUChar where+ geq = (==)++#if defined(HTYPE_UID_T)+instance GEq CUid where+ geq = (==)+#endif++instance GEq CUInt where+ geq = (==)++instance GEq CUIntMax where+ geq = (==)++instance GEq CUIntPtr where+ geq = (==)++instance GEq CULLong where+ geq = (==)++instance GEq CULong where+ geq = (==)++instance GEq CUSeconds where+ geq = (==)++instance GEq CUShort where+ geq = (==)++instance GEq CWchar where+ geq = (==)++instance GEq DecidedStrictness where+ geq = geqdefault++instance GEq Double where+ geq = (==)++instance GEq a => GEq (Down a) where+ geq = geqdefault++instance GEq a => GEq (Dual a) where+ geq = geqdefault++instance (GEq a, GEq b) => GEq (Either a b) where+ geq = geqdefault++instance GEq Errno where+ geq = (==)++instance GEq ExitCode where+ geq = geqdefault++instance GEq Fd where+ geq = (==)++instance GEq a => GEq (Monoid.First a) where+ geq = geqdefault++instance GEq a => GEq (Semigroup.First a) where+ geq = geqdefault++instance GEq Fixity where+ geq = geqdefault++instance GEq Float where+ geq = (==)++instance GEq (ForeignPtr a) where+ geq = (==)++instance GEq (FunPtr a) where+ geq = (==)++instance GEq GeneralCategory where+ geq = (==)++instance GEq Handle where+ geq = (==)++instance GEq HandlePosn where+ geq = (==)++instance GEq a => GEq (Identity a) where+ geq = geqdefault++instance GEq Int where+ geq = (==)++instance GEq Int8 where+ geq = (==)++instance GEq Int16 where+ geq = (==)++instance GEq Int32 where+ geq = (==)++instance GEq Int64 where+ geq = (==)++instance GEq Integer where+ geq = (==)++instance GEq IntPtr where+ geq = (==)++instance GEq IOError where+ geq = (==)++instance GEq IOErrorType where+ geq = (==)++instance GEq IOMode where+ geq = (==)++instance GEq c => GEq (K1 i c p) where+ geq = geqdefault++instance GEq a => GEq (Monoid.Last a) where+ geq = geqdefault++instance GEq a => GEq (Semigroup.Last a) where+ geq = geqdefault++instance GEq (f p) => GEq (M1 i c f p) where+ geq = geqdefault++instance GEq a => GEq (Maybe a) where+ geq = geqdefault++instance GEq a => GEq (Max a) where+ geq = geqdefault++instance GEq a => GEq (Min a) where+ geq = geqdefault++instance GEq Natural where+ geq = (==)++instance GEq a => GEq (NonEmpty a) where+ geq = geqdefault++instance GEq Ordering where+ geq = geqdefault++instance GEq p => GEq (Par1 p) where+ geq = geqdefault++instance GEq a => GEq (Product a) where+ geq = geqdefault++instance GEq (Proxy s) where+ geq = geqdefault++instance GEq (Ptr a) where+ geq = (==)++instance GEq (f p) => GEq (Rec1 f p) where+ geq = geqdefault++instance GEq SeekMode where+ geq = (==)++instance GEq (StablePtr a) where+ geq = (==)++instance GEq SourceStrictness where+ geq = geqdefault++instance GEq SourceUnpackedness where+ geq = geqdefault++instance GEq a => GEq (Sum a) where+ geq = geqdefault++instance GEq (U1 p) where+ geq = geqdefault++instance GEq (UAddr p) where+ geq = geqdefault++instance GEq (UChar p) where+ geq = geqdefault++instance GEq (UDouble p) where+ geq = geqdefault++instance GEq (UFloat p) where+ geq = geqdefault++instance GEq (UInt p) where+ geq = geqdefault++instance GEq (UWord p) where+ geq = geqdefault++instance GEq Version where+ geq = (==)++instance GEq Void where+ geq = (==)++instance GEq Word where+ geq = (==)++instance GEq Word8 where+ geq = (==)++instance GEq Word16 where+ geq = (==)++instance GEq Word32 where+ geq = (==)++instance GEq Word64 where+ geq = (==)++instance GEq WordPtr where+ geq = (==)++instance GEq m => GEq (WrappedMonoid m) where+ geq = geqdefault++instance GEq a => GEq (ZipList a) where+ geq = geqdefault++#if MIN_VERSION_base(4,10,0)+instance GEq CBool where+ geq = (==)++# if defined(HTYPE_BLKSIZE_T)+instance GEq CBlkSize where+ geq = (==)+# endif++# if defined(HTYPE_BLKCNT_T)+instance GEq CBlkCnt where+ geq = (==)+# endif++# if defined(HTYPE_CLOCKID_T)+instance GEq CClockId where+ geq = (==)+# endif++# if defined(HTYPE_FSBLKCNT_T)+instance GEq CFsBlkCnt where+ geq = (==)+# endif++# if defined(HTYPE_FSFILCNT_T)+instance GEq CFsFilCnt where+ geq = (==)+# endif++# if defined(HTYPE_ID_T)+instance GEq CId where+ geq = (==)+# endif++# if defined(HTYPE_KEY_T)+instance GEq CKey where+ geq = (==)+# endif++# if defined(HTYPE_TIMER_T)+instance GEq CTimer where+ geq = (==)+# endif+#endif
src/Generics/Deriving/Foldable.hs view
@@ -1,175 +1,274 @@-{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - -module Generics.Deriving.Foldable ( - -- * Foldable class - GFoldable(..) - - -- * Default method - , gfoldMapdefault - - -- * Derived functions - , gtoList - , gconcat - , gconcatMap - , gand - , gor - , gany - , gall - , gsum - , gproduct - , gmaximum - , gmaximumBy - , gminimum - , gminimumBy - , gelem - , gnotElem - , gfind - ) where - -import Data.Maybe -import Data.Monoid -import Generics.Deriving.Base -import Generics.Deriving.Instances () - --------------------------------------------------------------------------------- --- Generic fold --------------------------------------------------------------------------------- - -class GFoldable' t where - gfoldMap' :: Monoid m => (a -> m) -> t a -> m - -instance GFoldable' U1 where - gfoldMap' _ U1 = mempty - -instance GFoldable' Par1 where - gfoldMap' f (Par1 a) = f a - -instance GFoldable' (K1 i c) where - gfoldMap' _ (K1 _) = mempty - -instance (GFoldable f) => GFoldable' (Rec1 f) where - gfoldMap' f (Rec1 a) = gfoldMap f a - -instance (GFoldable' f) => GFoldable' (M1 i c f) where - gfoldMap' f (M1 a) = gfoldMap' f a - -instance (GFoldable' f, GFoldable' g) => GFoldable' (f :+: g) where - gfoldMap' f (L1 a) = gfoldMap' f a - gfoldMap' f (R1 a) = gfoldMap' f a - -instance (GFoldable' f, GFoldable' g) => GFoldable' (f :*: g) where - gfoldMap' f (a :*: b) = mappend (gfoldMap' f a) (gfoldMap' f b) - -instance (GFoldable f, GFoldable' g) => GFoldable' (f :.: g) where - gfoldMap' f (Comp1 x) = gfoldMap (gfoldMap' f) x - - -class GFoldable t where - gfoldMap :: Monoid m => (a -> m) -> t a -> m -#if __GLASGOW_HASKELL__ >= 701 - default gfoldMap :: (Generic1 t, GFoldable' (Rep1 t), Monoid m) - => (a -> m) -> t a -> m - gfoldMap = gfoldMapdefault -#endif - - gfold :: Monoid m => t m -> m - gfold = gfoldMap id - - gfoldr :: (a -> b -> b) -> b -> t a -> b - gfoldr f z t = appEndo (gfoldMap (Endo . f) t) z - - gfoldr' :: (a -> b -> b) -> b -> t a -> b - gfoldr' f z0 xs = gfoldl f' id xs z0 - where f' k x z = k $! f x z - - gfoldl :: (a -> b -> a) -> a -> t b -> a - gfoldl f z t = appEndo (getDual (gfoldMap (Dual . Endo . flip f) t)) z - - gfoldl' :: (a -> b -> a) -> a -> t b -> a - gfoldl' f z0 xs = gfoldr f' id xs z0 - where f' x k z = k $! f z x - - gfoldr1 :: (a -> a -> a) -> t a -> a - gfoldr1 f xs = fromMaybe (error "gfoldr1: empty structure") - (gfoldr mf Nothing xs) - where - mf x Nothing = Just x - mf x (Just y) = Just (f x y) - - gfoldl1 :: (a -> a -> a) -> t a -> a - gfoldl1 f xs = fromMaybe (error "foldl1: empty structure") - (gfoldl mf Nothing xs) - where - mf Nothing y = Just y - mf (Just x) y = Just (f x y) - -gfoldMapdefault :: (Generic1 t, GFoldable' (Rep1 t), Monoid m) - => (a -> m) -> t a -> m -gfoldMapdefault f x = gfoldMap' f (from1 x) - --- Base types instances -instance GFoldable Maybe where - gfoldMap = gfoldMapdefault - -instance GFoldable [] where - gfoldMap = gfoldMapdefault - -gtoList :: GFoldable t => t a -> [a] -gtoList = gfoldr (:) [] - -gconcat :: GFoldable t => t [a] -> [a] -gconcat = gfold - -gconcatMap :: GFoldable t => (a -> [b]) -> t a -> [b] -gconcatMap = gfoldMap - -gand :: GFoldable t => t Bool -> Bool -gand = getAll . gfoldMap All - -gor :: GFoldable t => t Bool -> Bool -gor = getAny . gfoldMap Any - -gany :: GFoldable t => (a -> Bool) -> t a -> Bool -gany p = getAny . gfoldMap (Any . p) - -gall :: GFoldable t => (a -> Bool) -> t a -> Bool -gall p = getAll . gfoldMap (All . p) - -gsum :: (GFoldable t, Num a) => t a -> a -gsum = getSum . gfoldMap Sum - -gproduct :: (GFoldable t, Num a) => t a -> a -gproduct = getProduct . gfoldMap Product - -gmaximum :: (GFoldable t, Ord a) => t a -> a -gmaximum = gfoldr1 max - -gmaximumBy :: GFoldable t => (a -> a -> Ordering) -> t a -> a -gmaximumBy cmp = gfoldr1 max' - where max' x y = case cmp x y of - GT -> x - _ -> y - -gminimum :: (GFoldable t, Ord a) => t a -> a -gminimum = gfoldr1 min - -gminimumBy :: GFoldable t => (a -> a -> Ordering) -> t a -> a -gminimumBy cmp = gfoldr1 min' - where min' x y = case cmp x y of - GT -> y - _ -> x - -gelem :: (GFoldable t, Eq a) => a -> t a -> Bool -gelem = gany . (==) - -gnotElem :: (GFoldable t, Eq a) => a -> t a -> Bool -gnotElem x = not . gelem x - -gfind :: GFoldable t => (a -> Bool) -> t a -> Maybe a -gfind p = listToMaybe . gconcatMap (\ x -> if p x then [x] else []) - +{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++module Generics.Deriving.Foldable (+ -- * Generic Foldable class+ GFoldable(..)++ -- * Default method+ , gfoldMapdefault++ -- * Derived functions+ , gtoList+ , gconcat+ , gconcatMap+ , gand+ , gor+ , gany+ , gall+ , gsum+ , gproduct+ , gmaximum+ , gmaximumBy+ , gminimum+ , gminimumBy+ , gelem+ , gnotElem+ , gfind++ -- * Internal Foldable class+ , GFoldable'(..)+ ) where++import Control.Applicative (Const, ZipList)++import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import qualified Data.Functor.Product as Functor (Product)+import qualified Data.Functor.Sum as Functor (Sum)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe+import qualified Data.Monoid as Monoid (First, Last, Product(..), Sum(..))+import Data.Monoid (All(..), Any(..), Dual(..), Endo(..))+import Data.Ord (Down)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg, Max, Min, WrappedMonoid)++import Generics.Deriving.Base++--------------------------------------------------------------------------------+-- Generic fold+--------------------------------------------------------------------------------++class GFoldable' t where+ gfoldMap' :: Monoid m => (a -> m) -> t a -> m++instance GFoldable' V1 where+ gfoldMap' _ _ = mempty++instance GFoldable' U1 where+ gfoldMap' _ U1 = mempty++instance GFoldable' Par1 where+ gfoldMap' f (Par1 a) = f a++instance GFoldable' (K1 i c) where+ gfoldMap' _ (K1 _) = mempty++instance (GFoldable f) => GFoldable' (Rec1 f) where+ gfoldMap' f (Rec1 a) = gfoldMap f a++instance (GFoldable' f) => GFoldable' (M1 i c f) where+ gfoldMap' f (M1 a) = gfoldMap' f a++instance (GFoldable' f, GFoldable' g) => GFoldable' (f :+: g) where+ gfoldMap' f (L1 a) = gfoldMap' f a+ gfoldMap' f (R1 a) = gfoldMap' f a++instance (GFoldable' f, GFoldable' g) => GFoldable' (f :*: g) where+ gfoldMap' f (a :*: b) = mappend (gfoldMap' f a) (gfoldMap' f b)++instance (GFoldable f, GFoldable' g) => GFoldable' (f :.: g) where+ gfoldMap' f (Comp1 x) = gfoldMap (gfoldMap' f) x++instance GFoldable' UAddr where+ gfoldMap' _ (UAddr _) = mempty++instance GFoldable' UChar where+ gfoldMap' _ (UChar _) = mempty++instance GFoldable' UDouble where+ gfoldMap' _ (UDouble _) = mempty++instance GFoldable' UFloat where+ gfoldMap' _ (UFloat _) = mempty++instance GFoldable' UInt where+ gfoldMap' _ (UInt _) = mempty++instance GFoldable' UWord where+ gfoldMap' _ (UWord _) = mempty++class GFoldable t where+ gfoldMap :: Monoid m => (a -> m) -> t a -> m+ default gfoldMap :: (Generic1 t, GFoldable' (Rep1 t), Monoid m)+ => (a -> m) -> t a -> m+ gfoldMap = gfoldMapdefault++ gfold :: Monoid m => t m -> m+ gfold = gfoldMap id++ gfoldr :: (a -> b -> b) -> b -> t a -> b+ gfoldr f z t = appEndo (gfoldMap (Endo . f) t) z++ gfoldr' :: (a -> b -> b) -> b -> t a -> b+ gfoldr' f z0 xs = gfoldl f' id xs z0+ where f' k x z = k $! f x z++ gfoldl :: (a -> b -> a) -> a -> t b -> a+ gfoldl f z t = appEndo (getDual (gfoldMap (Dual . Endo . flip f) t)) z++ gfoldl' :: (a -> b -> a) -> a -> t b -> a+ gfoldl' f z0 xs = gfoldr f' id xs z0+ where f' x k z = k $! f z x++ gfoldr1 :: (a -> a -> a) -> t a -> a+ gfoldr1 f xs = fromMaybe (error "gfoldr1: empty structure")+ (gfoldr mf Nothing xs)+ where+ mf x Nothing = Just x+ mf x (Just y) = Just (f x y)++ gfoldl1 :: (a -> a -> a) -> t a -> a+ gfoldl1 f xs = fromMaybe (error "foldl1: empty structure")+ (gfoldl mf Nothing xs)+ where+ mf Nothing y = Just y+ mf (Just x) y = Just (f x y)++gfoldMapdefault :: (Generic1 t, GFoldable' (Rep1 t), Monoid m)+ => (a -> m) -> t a -> m+gfoldMapdefault f x = gfoldMap' f (from1 x)++-- Base types instances+instance GFoldable ((,) a) where+ gfoldMap = gfoldMapdefault++instance GFoldable [] where+ gfoldMap = gfoldMapdefault++instance GFoldable (Arg a) where+ gfoldMap = gfoldMapdefault++instance GFoldable Complex where+ gfoldMap = gfoldMapdefault++instance GFoldable (Const m) where+ gfoldMap = gfoldMapdefault++instance GFoldable Down where+ gfoldMap = gfoldMapdefault++instance GFoldable Dual where+ gfoldMap = gfoldMapdefault++instance GFoldable (Either a) where+ gfoldMap = gfoldMapdefault++instance GFoldable Monoid.First where+ gfoldMap = gfoldMapdefault++instance GFoldable (Semigroup.First) where+ gfoldMap = gfoldMapdefault++instance GFoldable Identity where+ gfoldMap = gfoldMapdefault++instance GFoldable Monoid.Last where+ gfoldMap = gfoldMapdefault++instance GFoldable Semigroup.Last where+ gfoldMap = gfoldMapdefault++instance GFoldable Max where+ gfoldMap = gfoldMapdefault++instance GFoldable Maybe where+ gfoldMap = gfoldMapdefault++instance GFoldable Min where+ gfoldMap = gfoldMapdefault++instance GFoldable NonEmpty where+ gfoldMap = gfoldMapdefault++instance GFoldable Monoid.Product where+ gfoldMap = gfoldMapdefault++instance (GFoldable f, GFoldable g) => GFoldable (Functor.Product f g) where+ gfoldMap = gfoldMapdefault++instance GFoldable Proxy where+ gfoldMap = gfoldMapdefault++instance GFoldable Monoid.Sum where+ gfoldMap = gfoldMapdefault++instance (GFoldable f, GFoldable g) => GFoldable (Functor.Sum f g) where+ gfoldMap = gfoldMapdefault++instance GFoldable WrappedMonoid where+ gfoldMap = gfoldMapdefault++instance GFoldable ZipList where+ gfoldMap = gfoldMapdefault++gtoList :: GFoldable t => t a -> [a]+gtoList = gfoldr (:) []++gconcat :: GFoldable t => t [a] -> [a]+gconcat = gfold++gconcatMap :: GFoldable t => (a -> [b]) -> t a -> [b]+gconcatMap = gfoldMap++gand :: GFoldable t => t Bool -> Bool+gand = getAll . gfoldMap All++gor :: GFoldable t => t Bool -> Bool+gor = getAny . gfoldMap Any++gany :: GFoldable t => (a -> Bool) -> t a -> Bool+gany p = getAny . gfoldMap (Any . p)++gall :: GFoldable t => (a -> Bool) -> t a -> Bool+gall p = getAll . gfoldMap (All . p)++gsum :: (GFoldable t, Num a) => t a -> a+gsum = Monoid.getSum . gfoldMap Monoid.Sum++gproduct :: (GFoldable t, Num a) => t a -> a+gproduct = Monoid.getProduct . gfoldMap Monoid.Product++gmaximum :: (GFoldable t, Ord a) => t a -> a+gmaximum = gfoldr1 max++gmaximumBy :: GFoldable t => (a -> a -> Ordering) -> t a -> a+gmaximumBy cmp = gfoldr1 max'+ where max' x y = case cmp x y of+ GT -> x+ _ -> y++gminimum :: (GFoldable t, Ord a) => t a -> a+gminimum = gfoldr1 min++gminimumBy :: GFoldable t => (a -> a -> Ordering) -> t a -> a+gminimumBy cmp = gfoldr1 min'+ where min' x y = case cmp x y of+ GT -> y+ _ -> x++gelem :: (GFoldable t, Eq a) => a -> t a -> Bool+gelem = gany . (==)++gnotElem :: (GFoldable t, Eq a) => a -> t a -> Bool+gnotElem x = not . gelem x++gfind :: GFoldable t => (a -> Bool) -> t a -> Maybe a+gfind p = listToMaybe . gconcatMap (\ x -> if p x then [x] else [])
src/Generics/Deriving/Functor.hs view
@@ -1,70 +1,182 @@-{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - -module Generics.Deriving.Functor ( - -- * GFunctor class - GFunctor(..) - - -- * Default method - , gmapdefault - - ) where - -import Generics.Deriving.Base -import Generics.Deriving.Instances () - --------------------------------------------------------------------------------- --- Generic fmap --------------------------------------------------------------------------------- - -class GFunctor' f where - gmap' :: (a -> b) -> f a -> f b - -instance GFunctor' U1 where - gmap' _ U1 = U1 - -instance GFunctor' Par1 where - gmap' f (Par1 a) = Par1 (f a) - -instance GFunctor' (K1 i c) where - gmap' _ (K1 a) = K1 a - -instance (GFunctor f) => GFunctor' (Rec1 f) where - gmap' f (Rec1 a) = Rec1 (gmap f a) - -instance (GFunctor' f) => GFunctor' (M1 i c f) where - gmap' f (M1 a) = M1 (gmap' f a) - -instance (GFunctor' f, GFunctor' g) => GFunctor' (f :+: g) where - gmap' f (L1 a) = L1 (gmap' f a) - gmap' f (R1 a) = R1 (gmap' f a) - -instance (GFunctor' f, GFunctor' g) => GFunctor' (f :*: g) where - gmap' f (a :*: b) = gmap' f a :*: gmap' f b - -instance (GFunctor f, GFunctor' g) => GFunctor' (f :.: g) where - gmap' f (Comp1 x) = Comp1 (gmap (gmap' f) x) - - -class GFunctor f where - gmap :: (a -> b) -> f a -> f b -#if __GLASGOW_HASKELL__ >= 701 - default gmap :: (Generic1 f, GFunctor' (Rep1 f)) - => (a -> b) -> f a -> f b - gmap = gmapdefault -#endif - -gmapdefault :: (Generic1 f, GFunctor' (Rep1 f)) - => (a -> b) -> f a -> f b -gmapdefault f = to1 . gmap' f . from1 - --- Base types instances -instance GFunctor Maybe where - gmap = gmapdefault - -instance GFunctor [] where - gmap = gmapdefault +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++module Generics.Deriving.Functor (+ -- * Generic Functor class+ GFunctor(..)++ -- * Default method+ , gmapdefault++ -- * Internal Functor class+ , GFunctor'(..)++ ) where++import Control.Applicative (Const, ZipList)++import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import qualified Data.Functor.Product as Functor (Product)+import qualified Data.Functor.Sum as Functor (Sum)+import Data.List.NonEmpty (NonEmpty)+import qualified Data.Monoid as Monoid (First, Last, Product, Sum)+import Data.Monoid (Alt, Dual)+import Data.Ord (Down)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg, Max, Min, WrappedMonoid)++import Generics.Deriving.Base++--------------------------------------------------------------------------------+-- Generic fmap+--------------------------------------------------------------------------------++class GFunctor' f where+ gmap' :: (a -> b) -> f a -> f b++instance GFunctor' V1 where+ gmap' _ x = case x of {}++instance GFunctor' U1 where+ gmap' _ U1 = U1++instance GFunctor' Par1 where+ gmap' f (Par1 a) = Par1 (f a)++instance GFunctor' (K1 i c) where+ gmap' _ (K1 a) = K1 a++instance (GFunctor f) => GFunctor' (Rec1 f) where+ gmap' f (Rec1 a) = Rec1 (gmap f a)++instance (GFunctor' f) => GFunctor' (M1 i c f) where+ gmap' f (M1 a) = M1 (gmap' f a)++instance (GFunctor' f, GFunctor' g) => GFunctor' (f :+: g) where+ gmap' f (L1 a) = L1 (gmap' f a)+ gmap' f (R1 a) = R1 (gmap' f a)++instance (GFunctor' f, GFunctor' g) => GFunctor' (f :*: g) where+ gmap' f (a :*: b) = gmap' f a :*: gmap' f b++instance (GFunctor f, GFunctor' g) => GFunctor' (f :.: g) where+ gmap' f (Comp1 x) = Comp1 (gmap (gmap' f) x)++instance GFunctor' UAddr where+ gmap' _ (UAddr a) = UAddr a++instance GFunctor' UChar where+ gmap' _ (UChar c) = UChar c++instance GFunctor' UDouble where+ gmap' _ (UDouble d) = UDouble d++instance GFunctor' UFloat where+ gmap' _ (UFloat f) = UFloat f++instance GFunctor' UInt where+ gmap' _ (UInt i) = UInt i++instance GFunctor' UWord where+ gmap' _ (UWord w) = UWord w++class GFunctor f where+ gmap :: (a -> b) -> f a -> f b+ default gmap :: (Generic1 f, GFunctor' (Rep1 f))+ => (a -> b) -> f a -> f b+ gmap = gmapdefault++gmapdefault :: (Generic1 f, GFunctor' (Rep1 f))+ => (a -> b) -> f a -> f b+gmapdefault f = to1 . gmap' f . from1++-- Base types instances+instance GFunctor ((->) r) where+ gmap = fmap++instance GFunctor ((,) a) where+ gmap = gmapdefault++instance GFunctor [] where+ gmap = gmapdefault++instance GFunctor f => GFunctor (Alt f) where+ gmap = gmapdefault++instance GFunctor (Arg a) where+ gmap = gmapdefault++instance GFunctor Complex where+ gmap = gmapdefault++instance GFunctor (Const m) where+ gmap = gmapdefault++instance GFunctor Down where+ gmap = gmapdefault++instance GFunctor Dual where+ gmap = gmapdefault++instance GFunctor (Either a) where+ gmap = gmapdefault++instance GFunctor Monoid.First where+ gmap = gmapdefault++instance GFunctor (Semigroup.First) where+ gmap = gmapdefault++instance GFunctor Identity where+ gmap = gmapdefault++instance GFunctor IO where+ gmap = fmap++instance GFunctor Monoid.Last where+ gmap = gmapdefault++instance GFunctor Semigroup.Last where+ gmap = gmapdefault++instance GFunctor Max where+ gmap = gmapdefault++instance GFunctor Maybe where+ gmap = gmapdefault++instance GFunctor Min where+ gmap = gmapdefault++instance GFunctor NonEmpty where+ gmap = gmapdefault++instance GFunctor Monoid.Product where+ gmap = gmapdefault++instance (GFunctor f, GFunctor g) => GFunctor (Functor.Product f g) where+ gmap = gmapdefault++instance GFunctor Proxy where+ gmap = gmapdefault++instance GFunctor Monoid.Sum where+ gmap = gmapdefault++instance (GFunctor f, GFunctor g) => GFunctor (Functor.Sum f g) where+ gmap = gmapdefault++instance GFunctor WrappedMonoid where+ gmap = gmapdefault++instance GFunctor ZipList where+ gmap = gmapdefault
src/Generics/Deriving/Instances.hs view
@@ -1,134 +1,106 @@-{-# LANGUAGE EmptyDataDecls #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE TypeFamilies #-} -{-# OPTIONS_GHC -fno-warn-orphans #-} - -module Generics.Deriving.Instances ( --- Only instances from Generics.Deriving.Base --- and the Generic1 instances -#if __GLASGOW_HASKELL__ < 705 - Rep1Maybe, Rep1List -#endif -#if __GLASGOW_HASKELL__ < 701 - -- * Representations for base types - , Rep0Char, Rep0Int, Rep0Float - , Rep0Maybe, Rep0List -#endif - ) where - -#if __GLASGOW_HASKELL__ < 705 -import Generics.Deriving.Base -#endif - -#if __GLASGOW_HASKELL__ < 701 --------------------------------------------------------------------------------- --- Representation for base types --------------------------------------------------------------------------------- - --- Representation types -{- -type Rep1Par1 = Par1 -instance Generic1 Par1 Rep1Par1 where - from1 = id - to1 = id - -type Rep1Rec1 f = Rec1 f -instance Generic1 (Rec1 f) (Rep1Rec1 f) where - from1 = id - to1 = id --} --- Kind * - -type Rep0Char = Rec0 Char -instance Generic Char where - type Rep Char = Rep0Char - from = K1 - to = unK1 - -type Rep0Int = Rec0 Int -instance Generic Int where - type Rep Int = Rep0Int - from = K1 - to = unK1 - -type Rep0Float = Rec0 Float -instance Generic Float where - type Rep Float = Rep0Float - from = K1 - to = unK1 - --- etc... - --- Kind * -> * - -type Rep0Maybe a = D1 Maybe_ (C1 Nothing_ U1 :+: C1 Just_ (Par0 a)) -instance Generic (Maybe a) where - type Rep (Maybe a) = Rep0Maybe a - from Nothing = M1 (L1 (M1 U1)) - from (Just x) = M1 (R1 (M1 (K1 x))) - to (M1 (L1 (M1 U1))) = Nothing - to (M1 (R1 (M1 (K1 x)))) = Just x - -type Rep0List a = D1 List__ ((C1 Nil__ U1) :+: (C1 Cons__ (Par0 a :*: Rec0 [a]))) -instance Generic [a] where - type Rep [a] = Rep0List a - from [] = M1 (L1 (M1 U1)) - from (h:t) = M1 (R1 (M1 (K1 h :*: K1 t))) - to (M1 (L1 (M1 U1))) = [] - to (M1 (R1 (M1 (K1 h :*: K1 t)))) = h : t -#endif - -#if __GLASGOW_HASKELL__ < 705 --- GHC 7.2 and 7.4 still need these instances; 7.6 doesn't - -data Maybe_ -data Nothing_ -data Just_ - -instance Datatype Maybe_ where - datatypeName _ = "Maybe" - moduleName _ = "Representation" - -instance Constructor Nothing_ where - conName _ = "Nothing" - -instance Constructor Just_ where - conName _ = "Just" - - -type Rep1Maybe = D1 Maybe_ (C1 Nothing_ U1 :+: C1 Just_ Par1) -instance Generic1 Maybe where - type Rep1 Maybe = Rep1Maybe - from1 Nothing = M1 (L1 (M1 U1)) - from1 (Just x) = M1 (R1 (M1 (Par1 x))) - to1 (M1 (L1 (M1 U1))) = Nothing - to1 (M1 (R1 (M1 (Par1 x)))) = Just x - - -data List__ -data Nil__ -data Cons__ - -instance Datatype List__ where - datatypeName _ = "[]" - moduleName _ = "Data.List" - -instance Constructor Nil__ where conName _ = "[]" -instance Constructor Cons__ where - conName _ = ":" - conFixity _ = Infix RightAssociative 5 - - -type Rep1List = D1 List__ ((C1 Nil__ U1) :+: (C1 Cons__ (Par1 :*: Rec1 []))) -instance Generic1 [] where - type Rep1 [] = Rep1List - from1 [] = M1 (L1 (M1 U1)) - from1 (h:t) = M1 (R1 (M1 (Par1 h :*: Rec1 t))) - to1 (M1 (L1 (M1 U1))) = [] - to1 (M1 (R1 (M1 (Par1 h :*: Rec1 t)))) = h : t - --- etc... - -#endif +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Generics.Deriving.Instances (+-- Only instances from GHC.Generics+-- and the Generic1 instances+#if !(MIN_VERSION_base(4,16,0))+ Rep0Tuple8+ , Rep0Tuple9+ , Rep0Tuple10+ , Rep0Tuple11+ , Rep0Tuple12+ , Rep0Tuple13+ , Rep0Tuple14+ , Rep0Tuple15+ , Rep1Tuple8+ , Rep1Tuple9+ , Rep1Tuple10+ , Rep1Tuple11+ , Rep1Tuple12+ , Rep1Tuple13+ , Rep1Tuple14+ , Rep1Tuple15+#endif+#if !(MIN_VERSION_base(4,14,0))+ , Rep0Kleisli+ , Rep1Kleisli+#endif+#if !(MIN_VERSION_base(4,12,0))+ , Rep0Down+ , Rep1Down+#endif+ ) where++#if !(MIN_VERSION_base(4,12,0))+import Data.Ord (Down(..))+#endif++#if !(MIN_VERSION_base(4,14,0))+import Control.Arrow (Kleisli(..))+#endif++#if !(MIN_VERSION_base(4,16,0))+import GHC.Generics+#endif++#if !(MIN_VERSION_base(4,16,0))+type Rep0Tuple8 a b c d e f g h = Rep (a, b, c, d, e, f, g, h)+type Rep0Tuple9 a b c d e f g h i = Rep (a, b, c, d, e, f, g, h, i)+type Rep0Tuple10 a b c d e f g h i j = Rep (a, b, c, d, e, f, g, h, i, j)+type Rep0Tuple11 a b c d e f g h i j k = Rep (a, b, c, d, e, f, g, h, i, j, k)+type Rep0Tuple12 a b c d e f g h i j k l = Rep (a, b, c, d, e, f, g, h, i, j, k, l)+type Rep0Tuple13 a b c d e f g h i j k l m = Rep (a, b, c, d, e, f, g, h, i, j, k, l, m)+type Rep0Tuple14 a b c d e f g h i j k l m n = Rep (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+type Rep0Tuple15 a b c d e f g h i j k l m n o = Rep (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+type Rep1Tuple8 a b c d e f g = Rep1 ((,,,,,,,) a b c d e f g)+type Rep1Tuple9 a b c d e f g h = Rep1 ((,,,,,,,,) a b c d e f g h)+type Rep1Tuple10 a b c d e f g h i = Rep1 ((,,,,,,,,,) a b c d e f g h i)+type Rep1Tuple11 a b c d e f g h i j = Rep1 ((,,,,,,,,,,) a b c d e f g h i j)+type Rep1Tuple12 a b c d e f g h i j k = Rep1 ((,,,,,,,,,,,) a b c d e f g h i j k)+type Rep1Tuple13 a b c d e f g h i j k l = Rep1 ((,,,,,,,,,,,,) a b c d e f g h i j k l)+type Rep1Tuple14 a b c d e f g h i j k l m = Rep1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m)+type Rep1Tuple15 a b c d e f g h i j k l m n = Rep1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n)+deriving instance Generic (a, b, c, d, e, f, g, h)+deriving instance Generic (a, b, c, d, e, f, g, h, i)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+deriving instance Generic1 ((,,,,,,,) a b c d e f g)+deriving instance Generic1 ((,,,,,,,,) a b c d e f g h)+deriving instance Generic1 ((,,,,,,,,,) a b c d e f g h i)+deriving instance Generic1 ((,,,,,,,,,,) a b c d e f g h i j)+deriving instance Generic1 ((,,,,,,,,,,,) a b c d e f g h i j k)+deriving instance Generic1 ((,,,,,,,,,,,,) a b c d e f g h i j k l)+deriving instance Generic1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m)+deriving instance Generic1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n)+#endif++#if !(MIN_VERSION_base(4,14,0))+type Rep0Kleisli m a b = Rep (Kleisli m a b)+type Rep1Kleisli m a = Rep1 (Kleisli m a)+deriving instance Generic (Kleisli m a b)+deriving instance Generic1 (Kleisli m a)+#endif++#if !(MIN_VERSION_base(4,12,0))+type Rep0Down a = Rep (Down a)+type Rep1Down = Rep1 Down+deriving instance Generic (Down a)+deriving instance Generic1 Down+#endif
src/Generics/Deriving/Monoid.hs view
@@ -1,217 +1,17 @@-{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleContexts #-} - -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - --- | This module provides two main features: --- --- 1. 'GMonoid', a generic version of the 'Monoid' type class, including instances --- of the types from "Data.Monoid" --- --- 2. Default generic definitions for the 'Monoid' methods 'mempty' and 'mappend' --- --- The generic defaults only work for types without alternatives (i.e. they have --- only one constructor). We cannot in general know how to deal with different --- constructors. - -module Generics.Deriving.Monoid ( - - -- * GMonoid type class - GMonoid(..), - - -- * Default definitions - -- ** GMonoid - gmemptydefault, - gmappenddefault, - - -- ** Monoid - -- | These functions can be used in a 'Monoid' instance. For example: - -- - -- @ - -- -- LANGUAGE DeriveGeneric - -- - -- import Generics.Deriving.Base (Generic) - -- import Generics.Deriving.Monoid - -- - -- data T a = C a (Maybe a) deriving Generic - -- - -- instance Monoid a => Monoid (T a) where - -- mempty = memptydefault - -- mappend = mappenddefault - -- @ - memptydefault, - mappenddefault, - - -- * The Monoid module - -- | This is exported for convenient access to the various wrapper types. - module Data.Monoid, - - ) where - --------------------------------------------------------------------------------- - -import Generics.Deriving.Base -import Generics.Deriving.Instances () -import Data.Monoid - --------------------------------------------------------------------------------- - -class GMonoid' f where - gmempty' :: f x - gmappend' :: f x -> f x -> f x - -instance GMonoid' U1 where - gmempty' = U1 - gmappend' U1 U1 = U1 - -instance GMonoid a => GMonoid' (K1 i a) where - gmempty' = K1 gmempty - gmappend' (K1 x) (K1 y) = K1 (x `gmappend` y) - -instance GMonoid' f => GMonoid' (M1 i c f) where - gmempty' = M1 gmempty' - gmappend' (M1 x) (M1 y) = M1 (x `gmappend'` y) - -instance (GMonoid' f, GMonoid' h) => GMonoid' (f :*: h) where - gmempty' = gmempty' :*: gmempty' - gmappend' (x1 :*: y1) (x2 :*: y2) = gmappend' x1 x2 :*: gmappend' y1 y2 - --------------------------------------------------------------------------------- - -gmemptydefault :: (Generic a, GMonoid' (Rep a)) => a -gmemptydefault = to gmempty' - -gmappenddefault :: (Generic a, GMonoid' (Rep a)) => a -> a -> a -gmappenddefault x y = to (gmappend' (from x) (from y)) - --------------------------------------------------------------------------------- - -class Monoid' f where - mempty' :: f x - mappend' :: f x -> f x -> f x - -instance Monoid' U1 where - mempty' = U1 - mappend' U1 U1 = U1 - -instance Monoid a => Monoid' (K1 i a) where - mempty' = K1 mempty - mappend' (K1 x) (K1 y) = K1 (x `mappend` y) - -instance Monoid' f => Monoid' (M1 i c f) where - mempty' = M1 mempty' - mappend' (M1 x) (M1 y) = M1 (x `mappend'` y) - -instance (Monoid' f, Monoid' h) => Monoid' (f :*: h) where - mempty' = mempty' :*: mempty' - mappend' (x1 :*: y1) (x2 :*: y2) = mappend' x1 x2 :*: mappend' y1 y2 - --------------------------------------------------------------------------------- - -memptydefault :: (Generic a, Monoid' (Rep a)) => a -memptydefault = to mempty' - -mappenddefault :: (Generic a, Monoid' (Rep a)) => a -> a -> a -mappenddefault x y = to (mappend' (from x) (from y)) - --------------------------------------------------------------------------------- - -class GMonoid a where - - -- | Generic 'mempty' - gmempty :: a - - -- | Generic 'mappend' - gmappend :: a -> a -> a - - -- | Generic 'mconcat' - gmconcat :: [a] -> a - gmconcat = foldr gmappend gmempty - -#if __GLASGOW_HASKELL__ >= 701 - default gmempty :: (Generic a, GMonoid' (Rep a)) => a - gmempty = to gmempty' - - default gmappend :: (Generic a, GMonoid' (Rep a)) => a -> a -> a - gmappend x y = to (gmappend' (from x) (from y)) -#endif - --------------------------------------------------------------------------------- - --- Instances that reuse Monoid -instance GMonoid Ordering where - gmempty = mempty - gmappend = mappend -instance GMonoid () where - gmempty = mempty - gmappend = mappend -instance GMonoid Any where - gmempty = mempty - gmappend = mappend -instance GMonoid All where - gmempty = mempty - gmappend = mappend -instance GMonoid (First a) where - gmempty = mempty - gmappend = mappend -instance GMonoid (Last a) where - gmempty = mempty - gmappend = mappend -instance Num a => GMonoid (Sum a) where - gmempty = mempty - gmappend = mappend -instance Num a => GMonoid (Product a) where - gmempty = mempty - gmappend = mappend -instance GMonoid [a] where - gmempty = mempty - gmappend = mappend -instance GMonoid (Endo a) where - gmempty = mempty - gmappend = mappend - --- Handwritten instances -instance GMonoid a => GMonoid (Dual a) where - gmempty = Dual gmempty - gmappend (Dual x) (Dual y) = Dual (gmappend y x) -instance GMonoid a => GMonoid (Maybe a) where - gmempty = Nothing - gmappend Nothing x = x - gmappend x Nothing = x - gmappend (Just x) (Just y) = Just (gmappend x y) -instance GMonoid b => GMonoid (a -> b) where - gmempty _ = gmempty - gmappend f g x = gmappend (f x) (g x) - --- Tuple instances -instance (GMonoid a,GMonoid b) => GMonoid (a,b) where - gmempty = (gmempty,gmempty) - gmappend (a1,b1) (a2,b2) = - (gmappend a1 a2,gmappend b1 b2) -instance (GMonoid a,GMonoid b,GMonoid c) => GMonoid (a,b,c) where - gmempty = (gmempty,gmempty,gmempty) - gmappend (a1,b1,c1) (a2,b2,c2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2) -instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d) => GMonoid (a,b,c,d) where - gmempty = (gmempty,gmempty,gmempty,gmempty) - gmappend (a1,b1,c1,d1) (a2,b2,c2,d2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2) -instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e) => GMonoid (a,b,c,d,e) where - gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty) - gmappend (a1,b1,c1,d1,e1) (a2,b2,c2,d2,e2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2) -instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f) => GMonoid (a,b,c,d,e,f) where - gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty) - gmappend (a1,b1,c1,d1,e1,f1) (a2,b2,c2,d2,e2,f2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2) -instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f,GMonoid g) => GMonoid (a,b,c,d,e,f,g) where - gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty) - gmappend (a1,b1,c1,d1,e1,f1,g1) (a2,b2,c2,d2,e2,f2,g2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2,gmappend g1 g2) -instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f,GMonoid g,GMonoid h) => GMonoid (a,b,c,d,e,f,g,h) where - gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty) - gmappend (a1,b1,c1,d1,e1,f1,g1,h1) (a2,b2,c2,d2,e2,f2,g2,h2) = - (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2,gmappend g1 g2,gmappend h1 h2) - +{-# LANGUAGE Safe #-}+{-# OPTIONS_GHC -Wno-orphans #-}++module Generics.Deriving.Monoid (module Generics.Deriving.Monoid.Internal) where++import Data.Semigroup (WrappedMonoid)++import Generics.Deriving.Monoid.Internal+import Generics.Deriving.Semigroup (GSemigroup(..))++instance GSemigroup a => GMonoid (Maybe a) where+ gmempty = Nothing+ gmappend = gsappend++instance GMonoid m => GMonoid (WrappedMonoid m) where+ gmempty = gmemptydefault+ gmappend = gmappenddefault
+ src/Generics/Deriving/Monoid/Internal.hs view
@@ -0,0 +1,239 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}++module Generics.Deriving.Monoid.Internal (++ -- * Introduction+ {- | This module provides two main features:++ 1. 'GMonoid', a generic version of the 'Monoid' type class, including instances+ of the types from "Data.Monoid"++ 2. Default generic definitions for the 'Monoid' methods 'mempty' and 'mappend'++ The generic defaults only work for types without alternatives (i.e. they have+ only one constructor). We cannot in general know how to deal with different+ constructors.+ -}++ -- * GMonoid type class+ GMonoid(..),++ -- * Default definitions+ -- ** GMonoid+ gmemptydefault,+ gmappenddefault,++ -- * Internal auxiliary class for GMonoid+ GMonoid'(..),++ -- ** Monoid+ {- | These functions can be used in a 'Monoid' instance. For example:++ @+ -- LANGUAGE DeriveGeneric++ import Generics.Deriving.Base (Generic)+ import Generics.Deriving.Monoid++ data T a = C a (Maybe a) deriving Generic++ instance Monoid a => Monoid (T a) where+ mempty = memptydefault+ mappend = mappenddefault+ @+ -}+ memptydefault,+ mappenddefault,++ -- * Internal auxiliary class for Monoid+ Monoid'(..),++ -- * The Monoid module+ -- | This is exported for convenient access to the various wrapper types.+ module Data.Monoid,++ ) where++--------------------------------------------------------------------------------++import Control.Applicative+import Data.Functor.Identity (Identity)+import Data.Monoid+import Data.Ord (Down)+import Data.Proxy (Proxy)+import Generics.Deriving.Base+import Generics.Deriving.Semigroup.Internal++--------------------------------------------------------------------------------++class GSemigroup' f => GMonoid' f where+ gmempty' :: f x+ gmappend' :: f x -> f x -> f x++instance GMonoid' U1 where+ gmempty' = U1+ gmappend' U1 U1 = U1++instance GMonoid a => GMonoid' (K1 i a) where+ gmempty' = K1 gmempty+ gmappend' (K1 x) (K1 y) = K1 (x `gmappend` y)++instance GMonoid' f => GMonoid' (M1 i c f) where+ gmempty' = M1 gmempty'+ gmappend' (M1 x) (M1 y) = M1 (x `gmappend'` y)++instance (GMonoid' f, GMonoid' h) => GMonoid' (f :*: h) where+ gmempty' = gmempty' :*: gmempty'+ gmappend' (x1 :*: y1) (x2 :*: y2) = gmappend' x1 x2 :*: gmappend' y1 y2++--------------------------------------------------------------------------------++gmemptydefault :: (Generic a, GMonoid' (Rep a)) => a+gmemptydefault = to gmempty'++gmappenddefault :: (Generic a, GMonoid' (Rep a)) => a -> a -> a+gmappenddefault x y = to (gmappend' (from x) (from y))++--------------------------------------------------------------------------------++class Monoid' f where+ mempty' :: f x+ mappend' :: f x -> f x -> f x++instance Monoid' U1 where+ mempty' = U1+ mappend' U1 U1 = U1++instance Monoid a => Monoid' (K1 i a) where+ mempty' = K1 mempty+ mappend' (K1 x) (K1 y) = K1 (x `mappend` y)++instance Monoid' f => Monoid' (M1 i c f) where+ mempty' = M1 mempty'+ mappend' (M1 x) (M1 y) = M1 (x `mappend'` y)++instance (Monoid' f, Monoid' h) => Monoid' (f :*: h) where+ mempty' = mempty' :*: mempty'+ mappend' (x1 :*: y1) (x2 :*: y2) = mappend' x1 x2 :*: mappend' y1 y2++--------------------------------------------------------------------------------++memptydefault :: (Generic a, Monoid' (Rep a)) => a+memptydefault = to mempty'++mappenddefault :: (Generic a, Monoid' (Rep a)) => a -> a -> a+mappenddefault x y = to (mappend' (from x) (from y))++--------------------------------------------------------------------------------++class GSemigroup a => GMonoid a where++ -- | Generic 'mempty'+ gmempty :: a++ -- | Generic 'mappend'+ gmappend :: a -> a -> a++ -- | Generic 'mconcat'+ gmconcat :: [a] -> a+ gmconcat = foldr gmappend gmempty++ default gmempty :: (Generic a, GMonoid' (Rep a)) => a+ gmempty = to gmempty'++ default gmappend :: (Generic a, GMonoid' (Rep a)) => a -> a -> a+ gmappend x y = to (gmappend' (from x) (from y))++--------------------------------------------------------------------------------++-- Instances that reuse Monoid+instance GMonoid Ordering where+ gmempty = mempty+ gmappend = mappend+instance GMonoid () where+ gmempty = mempty+ gmappend = mappend+instance GMonoid Any where+ gmempty = mempty+ gmappend = mappend+instance GMonoid All where+ gmempty = mempty+ gmappend = mappend+instance GMonoid (First a) where+ gmempty = mempty+ gmappend = mappend+instance GMonoid (Last a) where+ gmempty = mempty+ gmappend = mappend+instance Num a => GMonoid (Sum a) where+ gmempty = mempty+ gmappend = mappend+instance Num a => GMonoid (Product a) where+ gmempty = mempty+ gmappend = mappend+instance GMonoid [a] where+ gmempty = mempty+ gmappend = mappend+instance GMonoid (Endo a) where+ gmempty = mempty+ gmappend = mappend+instance Alternative f => GMonoid (Alt f a) where+ gmempty = mempty+ gmappend = mappend++-- Handwritten instances+instance GMonoid a => GMonoid (Dual a) where+ gmempty = Dual gmempty+ gmappend (Dual x) (Dual y) = Dual (gmappend y x)+instance GMonoid b => GMonoid (a -> b) where+ gmempty _ = gmempty+ gmappend f g x = gmappend (f x) (g x)+instance GMonoid a => GMonoid (Const a b) where+ gmempty = gmemptydefault+ gmappend = gmappenddefault+instance GMonoid a => GMonoid (Down a) where+ gmempty = gmemptydefault+ gmappend = gmappenddefault++instance GMonoid (Proxy s) where+ gmempty = memptydefault+ gmappend = mappenddefault++instance GMonoid a => GMonoid (Identity a) where+ gmempty = gmemptydefault+ gmappend = gmappenddefault++-- Tuple instances+instance (GMonoid a,GMonoid b) => GMonoid (a,b) where+ gmempty = (gmempty,gmempty)+ gmappend (a1,b1) (a2,b2) =+ (gmappend a1 a2,gmappend b1 b2)+instance (GMonoid a,GMonoid b,GMonoid c) => GMonoid (a,b,c) where+ gmempty = (gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1) (a2,b2,c2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2)+instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d) => GMonoid (a,b,c,d) where+ gmempty = (gmempty,gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1,d1) (a2,b2,c2,d2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2)+instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e) => GMonoid (a,b,c,d,e) where+ gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1,d1,e1) (a2,b2,c2,d2,e2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2)+instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f) => GMonoid (a,b,c,d,e,f) where+ gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1,d1,e1,f1) (a2,b2,c2,d2,e2,f2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2)+instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f,GMonoid g) => GMonoid (a,b,c,d,e,f,g) where+ gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1,d1,e1,f1,g1) (a2,b2,c2,d2,e2,f2,g2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2,gmappend g1 g2)+instance (GMonoid a,GMonoid b,GMonoid c,GMonoid d,GMonoid e,GMonoid f,GMonoid g,GMonoid h) => GMonoid (a,b,c,d,e,f,g,h) where+ gmempty = (gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty,gmempty)+ gmappend (a1,b1,c1,d1,e1,f1,g1,h1) (a2,b2,c2,d2,e2,f2,g2,h2) =+ (gmappend a1 a2,gmappend b1 b2,gmappend c1 c2,gmappend d1 d2,gmappend e1 e2,gmappend f1 f2,gmappend g1 g2,gmappend h1 h2)
+ src/Generics/Deriving/Semigroup.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE Safe #-}+{-# OPTIONS_GHC -Wno-orphans #-}++module Generics.Deriving.Semigroup (module Generics.Deriving.Semigroup.Internal) where++import Data.Semigroup (WrappedMonoid(..))++import Generics.Deriving.Monoid.Internal (GMonoid(..))+import Generics.Deriving.Semigroup.Internal++instance GMonoid m => GSemigroup (WrappedMonoid m) where+ gsappend (WrapMonoid a) (WrapMonoid b) = WrapMonoid (gmappend a b)
+ src/Generics/Deriving/Semigroup/Internal.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}++module Generics.Deriving.Semigroup.Internal (+ -- * Generic semigroup class+ GSemigroup(..)++ -- * Default definition+ , gsappenddefault++ -- * Internal semigroup class+ , GSemigroup'(..)++ ) where++import Control.Applicative+import Data.Functor.Identity (Identity)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Monoid as Monoid hiding ((<>))+import Data.Ord (Down)+import Data.Proxy (Proxy)+import Data.Semigroup as Semigroup+import Data.Void (Void)+import Generics.Deriving.Base++-------------------------------------------------------------------------------++infixr 6 `gsappend'`+class GSemigroup' f where+ gsappend' :: f x -> f x -> f x++instance GSemigroup' U1 where+ gsappend' U1 U1 = U1++instance GSemigroup a => GSemigroup' (K1 i a) where+ gsappend' (K1 x) (K1 y) = K1 (gsappend x y)++instance GSemigroup' f => GSemigroup' (M1 i c f) where+ gsappend' (M1 x) (M1 y) = M1 (gsappend' x y)++instance (GSemigroup' f, GSemigroup' g) => GSemigroup' (f :*: g) where+ gsappend' (x1 :*: y1) (x2 :*: y2) = gsappend' x1 x2 :*: gsappend' y1 y2++-------------------------------------------------------------------------------++infixr 6 `gsappend`+class GSemigroup a where+ gsappend :: a -> a -> a+ default gsappend :: (Generic a, GSemigroup' (Rep a)) => a -> a -> a+ gsappend = gsappenddefault++ gstimes :: Integral b => b -> a -> a+ gstimes y0 x0+ | y0 <= 0 = error "gstimes: positive multiplier expected"+ | otherwise = f x0 y0+ where+ f x y+ | even y = f (gsappend x x) (y `quot` 2)+ | y == 1 = x+ | otherwise = g (gsappend x x) (pred y `quot` 2) x+ g x y z+ | even y = g (gsappend x x) (y `quot` 2) z+ | y == 1 = gsappend x z+ | otherwise = g (gsappend x x) (pred y `quot` 2) (gsappend x z)++ gsconcat :: NonEmpty a -> a+ gsconcat (a :| as) = go a as where+ go b (c:cs) = gsappend b (go c cs)+ go b [] = b++infixr 6 `gsappenddefault`+gsappenddefault :: (Generic a, GSemigroup' (Rep a)) => a -> a -> a+gsappenddefault x y = to (gsappend' (from x) (from y))++-------------------------------------------------------------------------------++-- Instances that reuse Monoid+instance GSemigroup Ordering where+ gsappend = mappend+instance GSemigroup () where+ gsappend = mappend+instance GSemigroup Any where+ gsappend = mappend+instance GSemigroup All where+ gsappend = mappend+instance GSemigroup (Monoid.First a) where+ gsappend = mappend+instance GSemigroup (Monoid.Last a) where+ gsappend = mappend+instance Num a => GSemigroup (Sum a) where+ gsappend = mappend+instance Num a => GSemigroup (Product a) where+ gsappend = mappend+instance GSemigroup [a] where+ gsappend = mappend+instance GSemigroup (Endo a) where+ gsappend = mappend+instance Alternative f => GSemigroup (Alt f a) where+ gsappend = mappend++-- Handwritten instances+instance GSemigroup a => GSemigroup (Dual a) where+ gsappend (Dual x) (Dual y) = Dual (gsappend y x)+instance GSemigroup a => GSemigroup (Maybe a) where+ gsappend Nothing x = x+ gsappend x Nothing = x+ gsappend (Just x) (Just y) = Just (gsappend x y)+instance GSemigroup b => GSemigroup (a -> b) where+ gsappend f g x = gsappend (f x) (g x)+instance GSemigroup a => GSemigroup (Const a b) where+ gsappend = gsappenddefault+instance GSemigroup a => GSemigroup (Down a) where+ gsappend = gsappenddefault+instance GSemigroup (Either a b) where+ gsappend Left{} b = b+ gsappend a _ = a++instance GSemigroup (Proxy s) where+ gsappend = gsappenddefault++instance GSemigroup a => GSemigroup (Identity a) where+ gsappend = gsappenddefault++instance GSemigroup Void where+ gsappend a _ = a++instance GSemigroup (Semigroup.First a) where+ gsappend = (<>)++instance GSemigroup (Semigroup.Last a) where+ gsappend = (<>)++instance Ord a => GSemigroup (Max a) where+ gsappend = (<>)++instance Ord a => GSemigroup (Min a) where+ gsappend = (<>)++instance GSemigroup (NonEmpty a) where+ gsappend = (<>)++-- Tuple instances+instance (GSemigroup a,GSemigroup b) => GSemigroup (a,b) where+ gsappend (a1,b1) (a2,b2) =+ (gsappend a1 a2,gsappend b1 b2)+instance (GSemigroup a,GSemigroup b,GSemigroup c) => GSemigroup (a,b,c) where+ gsappend (a1,b1,c1) (a2,b2,c2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2)+instance (GSemigroup a,GSemigroup b,GSemigroup c,GSemigroup d) => GSemigroup (a,b,c,d) where+ gsappend (a1,b1,c1,d1) (a2,b2,c2,d2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2,gsappend d1 d2)+instance (GSemigroup a,GSemigroup b,GSemigroup c,GSemigroup d,GSemigroup e) => GSemigroup (a,b,c,d,e) where+ gsappend (a1,b1,c1,d1,e1) (a2,b2,c2,d2,e2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2,gsappend d1 d2,gsappend e1 e2)+instance (GSemigroup a,GSemigroup b,GSemigroup c,GSemigroup d,GSemigroup e,GSemigroup f) => GSemigroup (a,b,c,d,e,f) where+ gsappend (a1,b1,c1,d1,e1,f1) (a2,b2,c2,d2,e2,f2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2,gsappend d1 d2,gsappend e1 e2,gsappend f1 f2)+instance (GSemigroup a,GSemigroup b,GSemigroup c,GSemigroup d,GSemigroup e,GSemigroup f,GSemigroup g) => GSemigroup (a,b,c,d,e,f,g) where+ gsappend (a1,b1,c1,d1,e1,f1,g1) (a2,b2,c2,d2,e2,f2,g2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2,gsappend d1 d2,gsappend e1 e2,gsappend f1 f2,gsappend g1 g2)+instance (GSemigroup a,GSemigroup b,GSemigroup c,GSemigroup d,GSemigroup e,GSemigroup f,GSemigroup g,GSemigroup h) => GSemigroup (a,b,c,d,e,f,g,h) where+ gsappend (a1,b1,c1,d1,e1,f1,g1,h1) (a2,b2,c2,d2,e2,f2,g2,h2) =+ (gsappend a1 a2,gsappend b1 b2,gsappend c1 c2,gsappend d1 d2,gsappend e1 e2,gsappend f1 f2,gsappend g1 g2,gsappend h1 h2)
src/Generics/Deriving/Show.hs view
@@ -1,142 +1,606 @@-{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE OverlappingInstances #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - -module Generics.Deriving.Show ( - -- * Generic show class - GShow(..) - - -- * Default definition - , gshowsPrecdefault - - ) where - - -import Generics.Deriving.Base -import Generics.Deriving.Instances () - --------------------------------------------------------------------------------- --- Generic show --------------------------------------------------------------------------------- - -appPrec :: Int -appPrec = 2 - -data Type = Rec | Tup | Pref | Inf String - -class GShow' f where - gshowsPrec' :: Type -> Int -> f a -> ShowS - isNullary :: f a -> Bool - isNullary = error "generic show (isNullary): unnecessary case" - -instance GShow' U1 where - gshowsPrec' _ _ U1 = id - isNullary _ = True - -instance (GShow c) => GShow' (K1 i c) where - gshowsPrec' _ n (K1 a) = gshowsPrec n a - isNullary _ = False - --- No instances for P or Rec because gshow is only applicable to types of kind * - -instance (GShow' a, Constructor c) => GShow' (M1 C c a) where - gshowsPrec' _ n c@(M1 x) = - case fixity of - Prefix -> showParen (n > appPrec && not (isNullary x)) - ( showString (conName c) - . if (isNullary x) then id else showChar ' ' - . showBraces t (gshowsPrec' t appPrec x)) - Infix _ m -> showParen (n > m) (showBraces t (gshowsPrec' t m x)) - where fixity = conFixity c - t = if (conIsRecord c) then Rec else - case (conIsTuple c) of - True -> Tup - False -> case fixity of - Prefix -> Pref - Infix _ _ -> Inf (show (conName c)) - showBraces :: Type -> ShowS -> ShowS - showBraces Rec p = showChar '{' . p . showChar '}' - showBraces Tup p = showChar '(' . p . showChar ')' - showBraces Pref p = p - showBraces (Inf _) p = p - conIsTuple y = tupleName (conName y) where - tupleName ('(':',':_) = True - tupleName _ = False - -instance (Selector s, GShow' a) => GShow' (M1 S s a) where - gshowsPrec' t n s@(M1 x) | selName s == "" = --showParen (n > appPrec) - (gshowsPrec' t n x) - | otherwise = showString (selName s) - . showString " = " - . gshowsPrec' t 0 x - isNullary (M1 x) = isNullary x - -instance (GShow' a) => GShow' (M1 D d a) where - gshowsPrec' t n (M1 x) = gshowsPrec' t n x - -instance (GShow' a, GShow' b) => GShow' (a :+: b) where - gshowsPrec' t n (L1 x) = gshowsPrec' t n x - gshowsPrec' t n (R1 x) = gshowsPrec' t n x - -instance (GShow' a, GShow' b) => GShow' (a :*: b) where - gshowsPrec' t@Rec n (a :*: b) = - gshowsPrec' t n a . showString ", " . gshowsPrec' t n b - gshowsPrec' t@(Inf s) n (a :*: b) = - gshowsPrec' t n a . showString s . gshowsPrec' t n b - gshowsPrec' t@Tup n (a :*: b) = - gshowsPrec' t n a . showChar ',' . gshowsPrec' t n b - gshowsPrec' t@Pref n (a :*: b) = - gshowsPrec' t (n+1) a . showChar ' ' . gshowsPrec' t (n+1) b - - -- If we have a product then it is not a nullary constructor - isNullary _ = False - - -class GShow a where - gshowsPrec :: Int -> a -> ShowS - gshows :: a -> ShowS - gshows = gshowsPrec 0 - gshow :: a -> String - gshow x = gshows x "" -#if __GLASGOW_HASKELL__ >= 701 - default gshowsPrec :: (Generic a, GShow' (Rep a)) - => Int -> a -> ShowS - gshowsPrec = gshowsPrecdefault - -instance (GShow a) => GShow (Maybe a) - -#else - -instance (GShow a) => GShow (Maybe a) where - gshowsPrec = gshowsPrecdefault - -#endif - -gshowsPrecdefault :: (Generic a, GShow' (Rep a)) - => Int -> a -> ShowS -gshowsPrecdefault n = gshowsPrec' Pref n . from - - --- Base types instances -instance GShow Char where gshowsPrec = showsPrec -instance GShow Int where gshowsPrec = showsPrec -instance GShow Float where gshowsPrec = showsPrec -instance GShow String where gshowsPrec = showsPrec -instance GShow Bool where gshowsPrec = showsPrec - -intersperse :: a -> [a] -> [a] -intersperse _ [] = [] -intersperse _ [h] = [h] -intersperse x (h:t) = h : x : (intersperse x t) - -instance (GShow a) => GShow [a] where - gshowsPrec _ l = showChar '[' - . foldr (.) id - (intersperse (showChar ',') (map (gshowsPrec 0) l)) - . showChar ']' +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++module Generics.Deriving.Show (+ -- * Generic show class+ GShow(..)++ -- * Default definition+ , gshowsPrecdefault++ -- * Internal show class+ , GShow'(..)++ ) where++import Control.Applicative (Const, ZipList)++import Data.Char (GeneralCategory)+import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import Data.Int+import Data.List.NonEmpty (NonEmpty)+import Data.Monoid (All, Alt, Any, Dual, Product, Sum)+import qualified Data.Monoid as Monoid (First, Last)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg, Max, Min, WrappedMonoid)+import Data.Version (Version)+import Data.Void (Void)+import Data.Word++import Foreign.C.Types+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Ptr++import Generics.Deriving.Base++import GHC.Exts hiding (Any)++import Numeric.Natural (Natural)++import System.Exit (ExitCode)+import System.IO (BufferMode, Handle, HandlePosn, IOMode, SeekMode)+import System.IO.Error (IOErrorType)+import System.Posix.Types++--------------------------------------------------------------------------------+-- Generic show+--------------------------------------------------------------------------------++intersperse :: a -> [a] -> [a]+intersperse _ [] = []+intersperse _ [h] = [h]+intersperse x (h:t) = h : x : (intersperse x t)++appPrec :: Int+appPrec = 2++data Type = Rec | Tup | Pref | Inf String++class GShow' f where+ gshowsPrec' :: Type -> Int -> f a -> ShowS+ isNullary :: f a -> Bool+ isNullary = error "generic show (isNullary): unnecessary case"++instance GShow' V1 where+ gshowsPrec' _ _ x = case x of {}++instance GShow' U1 where+ gshowsPrec' _ _ U1 = id+ isNullary _ = True++instance (GShow c) => GShow' (K1 i c) where+ gshowsPrec' _ n (K1 a) = gshowsPrec n a+ isNullary _ = False++-- No instances for P or Rec because gshow is only applicable to types of kind *++instance (GShow' a, Constructor c) => GShow' (M1 C c a) where+ gshowsPrec' _ n c@(M1 x) =+ case fixity of+ Prefix -> showParen (n > appPrec && not (isNullary x))+ ( showString (conName c)+ . if (isNullary x) then id else showChar ' '+ . showBraces t (gshowsPrec' t appPrec x))+ Infix _ m -> showParen (n > m) (showBraces t (gshowsPrec' t m x))+ where fixity = conFixity c+ t = if (conIsRecord c) then Rec else+ case (conIsTuple c) of+ True -> Tup+ False -> case fixity of+ Prefix -> Pref+ Infix _ _ -> Inf (show (conName c))+ showBraces :: Type -> ShowS -> ShowS+ showBraces Rec p = showChar '{' . p . showChar '}'+ showBraces Tup p = showChar '(' . p . showChar ')'+ showBraces Pref p = p+ showBraces (Inf _) p = p++ conIsTuple :: C1 c f p -> Bool+ conIsTuple y = tupleName (conName y) where+ tupleName ('(':',':_) = True+ tupleName _ = False++instance (Selector s, GShow' a) => GShow' (M1 S s a) where+ gshowsPrec' t n s@(M1 x) | selName s == "" = --showParen (n > appPrec)+ (gshowsPrec' t n x)+ | otherwise = showString (selName s)+ . showString " = "+ . gshowsPrec' t 0 x+ isNullary (M1 x) = isNullary x++instance (GShow' a) => GShow' (M1 D d a) where+ gshowsPrec' t n (M1 x) = gshowsPrec' t n x++instance (GShow' a, GShow' b) => GShow' (a :+: b) where+ gshowsPrec' t n (L1 x) = gshowsPrec' t n x+ gshowsPrec' t n (R1 x) = gshowsPrec' t n x++instance (GShow' a, GShow' b) => GShow' (a :*: b) where+ gshowsPrec' t@Rec n (a :*: b) =+ gshowsPrec' t n a . showString ", " . gshowsPrec' t n b+ gshowsPrec' t@(Inf s) n (a :*: b) =+ gshowsPrec' t n a . showString s . gshowsPrec' t n b+ gshowsPrec' t@Tup n (a :*: b) =+ gshowsPrec' t n a . showChar ',' . gshowsPrec' t n b+ gshowsPrec' t@Pref n (a :*: b) =+ gshowsPrec' t (n+1) a . showChar ' ' . gshowsPrec' t (n+1) b++ -- If we have a product then it is not a nullary constructor+ isNullary _ = False++-- Unboxed types+instance GShow' UChar where+ gshowsPrec' _ _ (UChar c) = showsPrec 0 (C# c) . showChar '#'+instance GShow' UDouble where+ gshowsPrec' _ _ (UDouble d) = showsPrec 0 (D# d) . showString "##"+instance GShow' UFloat where+ gshowsPrec' _ _ (UFloat f) = showsPrec 0 (F# f) . showChar '#'+instance GShow' UInt where+ gshowsPrec' _ _ (UInt i) = showsPrec 0 (I# i) . showChar '#'+instance GShow' UWord where+ gshowsPrec' _ _ (UWord w) = showsPrec 0 (W# w) . showString "##"+++class GShow a where+ gshowsPrec :: Int -> a -> ShowS+ default gshowsPrec :: (Generic a, GShow' (Rep a))+ => Int -> a -> ShowS+ gshowsPrec = gshowsPrecdefault++ gshows :: a -> ShowS+ gshows = gshowsPrec 0++ gshow :: a -> String+ gshow x = gshows x ""++ gshowList :: [a] -> ShowS+ gshowList l = showChar '['+ . foldr (.) id+ (intersperse (showChar ',') (map (gshowsPrec 0) l))+ . showChar ']'++gshowsPrecdefault :: (Generic a, GShow' (Rep a))+ => Int -> a -> ShowS+gshowsPrecdefault n = gshowsPrec' Pref n . from+++-- Base types instances+-- Base types instances+instance GShow () where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b) => GShow (a, b) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b, GShow c) => GShow (a, b, c) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b, GShow c, GShow d) => GShow (a, b, c, d) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b, GShow c, GShow d, GShow e) => GShow (a, b, c, d, e) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b, GShow c, GShow d, GShow e, GShow f)+ => GShow (a, b, c, d, e, f) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b, GShow c, GShow d, GShow e, GShow f, GShow g)+ => GShow (a, b, c, d, e, f, g) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow [a] where+ gshowsPrec _ = gshowList++instance (GShow (f p), GShow (g p)) => GShow ((f :+: g) p) where+ gshowsPrec = gshowsPrecdefault++instance (GShow (f p), GShow (g p)) => GShow ((f :*: g) p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (f (g p)) => GShow ((f :.: g) p) where+ gshowsPrec = gshowsPrecdefault++instance GShow All where+ gshowsPrec = gshowsPrecdefault++instance GShow (f a) => GShow (Alt f a) where+ gshowsPrec = gshowsPrecdefault++instance GShow Any where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b) => GShow (Arg a b) where+ gshowsPrec = gshowsPrecdefault++instance GShow Associativity where+ gshowsPrec = gshowsPrecdefault++instance GShow Bool where+ gshowsPrec = gshowsPrecdefault++instance GShow BufferMode where+ gshowsPrec = showsPrec++#if defined(HTYPE_CC_T)+instance GShow CCc where+ gshowsPrec = showsPrec+#endif++instance GShow CChar where+ gshowsPrec = showsPrec++instance GShow CClock where+ gshowsPrec = showsPrec++#if defined(HTYPE_DEV_T)+instance GShow CDev where+ gshowsPrec = showsPrec+#endif++instance GShow CDouble where+ gshowsPrec = showsPrec++instance GShow CFloat where+ gshowsPrec = showsPrec++#if defined(HTYPE_GID_T)+instance GShow CGid where+ gshowsPrec = showsPrec+#endif++instance GShow Char where+ gshowsPrec = showsPrec+ gshowList = showList++#if defined(HTYPE_INO_T)+instance GShow CIno where+ gshowsPrec = showsPrec+#endif++instance GShow CInt where+ gshowsPrec = showsPrec++instance GShow CIntMax where+ gshowsPrec = showsPrec++instance GShow CIntPtr where+ gshowsPrec = showsPrec++instance GShow CLLong where+ gshowsPrec = showsPrec++instance GShow CLong where+ gshowsPrec = showsPrec++#if defined(HTYPE_MODE_T)+instance GShow CMode where+ gshowsPrec = showsPrec+#endif++#if defined(HTYPE_NLINK_T)+instance GShow CNlink where+ gshowsPrec = showsPrec+#endif++#if defined(HTYPE_OFF_T)+instance GShow COff where+ gshowsPrec = showsPrec+#endif++instance GShow a => GShow (Complex a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Const a b) where+ gshowsPrec = gshowsPrecdefault++#if defined(HTYPE_PID_T)+instance GShow CPid where+ gshowsPrec = showsPrec+#endif++instance GShow CPtrdiff where+ gshowsPrec = showsPrec++#if defined(HTYPE_RLIM_T)+instance GShow CRLim where+ gshowsPrec = showsPrec+#endif++instance GShow CSChar where+ gshowsPrec = showsPrec++#if defined(HTYPE_SPEED_T)+instance GShow CSpeed where+ gshowsPrec = showsPrec+#endif++instance GShow CSUSeconds where+ gshowsPrec = showsPrec++instance GShow CShort where+ gshowsPrec = showsPrec++instance GShow CSigAtomic where+ gshowsPrec = showsPrec++instance GShow CSize where+ gshowsPrec = showsPrec++#if defined(HTYPE_SSIZE_T)+instance GShow CSsize where+ gshowsPrec = showsPrec+#endif++#if defined(HTYPE_TCFLAG_T)+instance GShow CTcflag where+ gshowsPrec = showsPrec+#endif++instance GShow CTime where+ gshowsPrec = showsPrec++instance GShow CUChar where+ gshowsPrec = showsPrec++#if defined(HTYPE_UID_T)+instance GShow CUid where+ gshowsPrec = showsPrec+#endif++instance GShow CUInt where+ gshowsPrec = showsPrec++instance GShow CUIntMax where+ gshowsPrec = showsPrec++instance GShow CUIntPtr where+ gshowsPrec = showsPrec++instance GShow CULLong where+ gshowsPrec = showsPrec++instance GShow CULong where+ gshowsPrec = showsPrec++instance GShow CUSeconds where+ gshowsPrec = showsPrec++instance GShow CUShort where+ gshowsPrec = showsPrec++instance GShow CWchar where+ gshowsPrec = showsPrec++instance GShow Double where+ gshowsPrec = showsPrec++instance GShow a => GShow (Down a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Dual a) where+ gshowsPrec = gshowsPrecdefault++instance (GShow a, GShow b) => GShow (Either a b) where+ gshowsPrec = gshowsPrecdefault++instance GShow ExitCode where+ gshowsPrec = gshowsPrecdefault++instance GShow Fd where+ gshowsPrec = showsPrec++instance GShow a => GShow (Monoid.First a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Semigroup.First a) where+ gshowsPrec = gshowsPrecdefault++instance GShow Fixity where+ gshowsPrec = gshowsPrecdefault++instance GShow Float where+ gshowsPrec = showsPrec++instance GShow (ForeignPtr a) where+ gshowsPrec = showsPrec++instance GShow (FunPtr a) where+ gshowsPrec = showsPrec++instance GShow GeneralCategory where+ gshowsPrec = showsPrec++instance GShow Handle where+ gshowsPrec = showsPrec++instance GShow HandlePosn where+ gshowsPrec = showsPrec++instance GShow a => GShow (Identity a) where+ gshowsPrec = gshowsPrecdefault++instance GShow Int where+ gshowsPrec = showsPrec++instance GShow Int8 where+ gshowsPrec = showsPrec++instance GShow Int16 where+ gshowsPrec = showsPrec++instance GShow Int32 where+ gshowsPrec = showsPrec++instance GShow Int64 where+ gshowsPrec = showsPrec++instance GShow Integer where+ gshowsPrec = showsPrec++instance GShow IntPtr where+ gshowsPrec = showsPrec++instance GShow IOError where+ gshowsPrec = showsPrec++instance GShow IOErrorType where+ gshowsPrec = showsPrec++instance GShow IOMode where+ gshowsPrec = showsPrec++instance GShow c => GShow (K1 i c p) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Monoid.Last a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Semigroup.Last a) where+ gshowsPrec = gshowsPrecdefault++instance GShow (f p) => GShow (M1 i c f p) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Max a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Maybe a) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Min a) where+ gshowsPrec = gshowsPrecdefault++instance GShow Natural where+ gshowsPrec = showsPrec++instance GShow a => GShow (NonEmpty a) where+ gshowsPrec = gshowsPrecdefault++instance GShow Ordering where+ gshowsPrec = gshowsPrecdefault++instance GShow p => GShow (Par1 p) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (Product a) where+ gshowsPrec = gshowsPrecdefault++instance GShow (Proxy s) where+ gshowsPrec = gshowsPrecdefault++instance GShow (Ptr a) where+ gshowsPrec = showsPrec++instance GShow (f p) => GShow (Rec1 f p) where+ gshowsPrec = gshowsPrecdefault++instance GShow SeekMode where+ gshowsPrec = showsPrec++instance GShow a => GShow (Sum a) where+ gshowsPrec = gshowsPrecdefault++instance GShow (U1 p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (UChar p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (UDouble p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (UFloat p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (UInt p) where+ gshowsPrec = gshowsPrecdefault++instance GShow (UWord p) where+ gshowsPrec = gshowsPrecdefault++instance GShow Version where+ gshowsPrec = gshowsPrecdefault++instance GShow Void where+ gshowsPrec = showsPrec++instance GShow Word where+ gshowsPrec = showsPrec++instance GShow Word8 where+ gshowsPrec = showsPrec++instance GShow Word16 where+ gshowsPrec = showsPrec++instance GShow Word32 where+ gshowsPrec = showsPrec++instance GShow Word64 where+ gshowsPrec = showsPrec++instance GShow WordPtr where+ gshowsPrec = showsPrec++instance GShow m => GShow (WrappedMonoid m) where+ gshowsPrec = gshowsPrecdefault++instance GShow a => GShow (ZipList a) where+ gshowsPrec = gshowsPrecdefault++#if MIN_VERSION_base(4,10,0)+instance GShow CBool where+ gshowsPrec = showsPrec++# if defined(HTYPE_BLKSIZE_T)+instance GShow CBlkSize where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_BLKCNT_T)+instance GShow CBlkCnt where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_CLOCKID_T)+instance GShow CClockId where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_FSBLKCNT_T)+instance GShow CFsBlkCnt where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_FSFILCNT_T)+instance GShow CFsFilCnt where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_ID_T)+instance GShow CId where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_KEY_T)+instance GShow CKey where+ gshowsPrec = showsPrec+# endif++# if defined(HTYPE_TIMER_T)+instance GShow CTimer where+ gshowsPrec = showsPrec+# endif+#endif
src/Generics/Deriving/TH.hs view
@@ -1,415 +1,1206 @@-{-# LANGUAGE TemplateHaskell, CPP #-} -{-# OPTIONS_GHC -w #-} - ------------------------------------------------------------------------------ --- | --- Module : Generics.Deriving.TH --- Copyright : (c) 2008--2009 Universiteit Utrecht --- License : BSD3 --- --- Maintainer : generics@haskell.org --- Stability : experimental --- Portability : non-portable --- --- This module contains Template Haskell code that can be used to --- automatically generate the boilerplate code for the generic deriving --- library. For now, it generates only the 'Generic' instance. --- Empty datatypes are not yet supported. ------------------------------------------------------------------------------ - --- Adapted from Generics.Regular.TH -module Generics.Deriving.TH ( - - deriveMeta - , deriveData - , deriveConstructors - , deriveSelectors - -#if __GLASGOW_HASKELL__ < 701 - , deriveAll - , deriveRepresentable0 - , deriveRep0 - , simplInstance -#endif - ) where - -import Generics.Deriving.Base - -import Language.Haskell.TH hiding (Fixity()) -import Language.Haskell.TH.Syntax (Lift(..)) - -import Data.List (intercalate) -import Control.Monad - --- | Given the names of a generic class, a type to instantiate, a function in --- the class and the default implementation, generates the code for a basic --- generic instance. -simplInstance :: Name -> Name -> Name -> Name -> Q [Dec] -simplInstance cl ty fn df = do - i <- reify (genRepName 0 ty) - x <- newName "x" - let typ = ForallT [PlainTV x] [] - ((foldl (\a -> AppT a . VarT . tyVarBndrToName) (ConT (genRepName 0 ty)) - (typeVariables i)) `AppT` (VarT x)) - fmap (: []) $ instanceD (cxt []) (conT cl `appT` conT ty) - [funD fn [clause [] (normalB (varE df `appE` - (sigE (global 'undefined) (return typ)))) []]] - - --- | Given the type and the name (as string) for the type to derive, --- generate the 'Data' instance, the 'Constructor' instances, the 'Selector' --- instances, and the 'Representable0' instance. -deriveAll :: Name -> Q [Dec] -deriveAll n = - do a <- deriveMeta n - b <- deriveRepresentable0 n - return (a ++ b) - --- | Given the type and the name (as string) for the type to derive, --- generate the 'Data' instance, the 'Constructor' instances, and the 'Selector' --- instances. -deriveMeta :: Name -> Q [Dec] -deriveMeta n = - do a <- deriveData n - b <- deriveConstructors n - c <- deriveSelectors n - return (a ++ b ++ c) - --- | Given a datatype name, derive a datatype and instance of class 'Datatype'. -deriveData :: Name -> Q [Dec] -deriveData = dataInstance - --- | Given a datatype name, derive datatypes and --- instances of class 'Constructor'. -deriveConstructors :: Name -> Q [Dec] -deriveConstructors = constrInstance - --- | Given a datatype name, derive datatypes and instances of class 'Selector'. -deriveSelectors :: Name -> Q [Dec] -deriveSelectors = selectInstance - --- | Given the type and the name (as string) for the Representable0 type --- synonym to derive, generate the 'Representable0' instance. -deriveRepresentable0 :: Name -> Q [Dec] -deriveRepresentable0 n = do - rep0 <- deriveRep0 n - inst <- deriveInst n - return $ rep0 ++ inst - --- | Derive only the 'Rep0' type synonym. Not needed if 'deriveRepresentable0' --- is used. -deriveRep0 :: Name -> Q [Dec] -deriveRep0 n = do - i <- reify n - fmap (:[]) $ tySynD (genRepName 0 n) (typeVariables i) (rep0Type n) - -deriveInst :: Name -> Q [Dec] -deriveInst t = do - i <- reify t - let typ q = foldl (\a -> AppT a . VarT . tyVarBndrToName) (ConT q) - (typeVariables i) -#if __GLASGOW_HASKELL__ >= 707 - let tyIns = TySynInstD ''Rep (fmap (TySynEqn [typ (genRepName 0 t)]) [typ t]) -#else - let tyIns = TySynInstD ''Rep [typ t] (typ (genRepName 0 t)) -#endif - fcs <- mkFrom t 1 0 t - tcs <- mkTo t 1 0 t - liftM (:[]) $ - instanceD (cxt []) (conT ''Generic `appT` return (typ t)) - [return tyIns, funD 'from fcs, funD 'to tcs] - - -dataInstance :: Name -> Q [Dec] -dataInstance n = do - i <- reify n - case i of - TyConI (DataD _ n _ _ _) -> mkInstance n - TyConI (NewtypeD _ n _ _ _) -> mkInstance n - _ -> return [] - where - mkInstance n = do - ds <- mkDataData n - is <- mkDataInstance n - return $ [ds,is] - -constrInstance :: Name -> Q [Dec] -constrInstance n = do - i <- reify n - case i of - TyConI (DataD _ n _ cs _) -> mkInstance n cs - TyConI (NewtypeD _ n _ c _) -> mkInstance n [c] - _ -> return [] - where - mkInstance n cs = do - ds <- mapM (mkConstrData n) cs - is <- mapM (mkConstrInstance n) cs - return $ ds ++ is - -selectInstance :: Name -> Q [Dec] -selectInstance n = do - i <- reify n - case i of - TyConI (DataD _ n _ cs _) -> mkInstance n cs - TyConI (NewtypeD _ n _ c _) -> mkInstance n [c] - _ -> return [] - where - mkInstance n cs = do - ds <- mapM (mkSelectData n) cs - is <- mapM (mkSelectInstance n) cs - return $ concat (ds ++ is) - -typeVariables :: Info -> [TyVarBndr] -typeVariables (TyConI (DataD _ _ tv _ _)) = tv -typeVariables (TyConI (NewtypeD _ _ tv _ _)) = tv -typeVariables _ = [] - -tyVarBndrToName :: TyVarBndr -> Name -tyVarBndrToName (PlainTV name) = name -tyVarBndrToName (KindedTV name _) = name - -stripRecordNames :: Con -> Con -stripRecordNames (RecC n f) = - NormalC n (map (\(_, s, t) -> (s, t)) f) -stripRecordNames c = c - -genName :: [Name] -> Name -genName = mkName . (++"_") . intercalate "_" . map nameBase - -genRepName :: Int -> Name -> Name -genRepName n = mkName . (++"_") . (("Rep" ++ show n) ++) . nameBase - -mkDataData :: Name -> Q Dec -mkDataData n = dataD (cxt []) (genName [n]) [] [] [] - -mkConstrData :: Name -> Con -> Q Dec -mkConstrData dt (NormalC n _) = - dataD (cxt []) (genName [dt, n]) [] [] [] -mkConstrData dt r@(RecC _ _) = - mkConstrData dt (stripRecordNames r) -mkConstrData dt (InfixC t1 n t2) = - mkConstrData dt (NormalC n [t1,t2]) - -mkSelectData :: Name -> Con -> Q [Dec] -mkSelectData dt r@(RecC n fs) = return (map one fs) - where one (f, _, _) = DataD [] (genName [dt, n, f]) [] [] [] -mkSelectData dt _ = return [] - - -mkDataInstance :: Name -> Q Dec -mkDataInstance n = - instanceD (cxt []) (appT (conT ''Datatype) (conT $ genName [n])) - [funD 'datatypeName [clause [wildP] (normalB (stringE (nameBase n))) []] - ,funD 'moduleName [clause [wildP] (normalB (stringE name)) []]] - where - name = maybe (error "Cannot fetch module name!") id (nameModule n) - -instance Lift Fixity where - lift Prefix = conE 'Prefix - lift (Infix a n) = conE 'Infix `appE` [| a |] `appE` [| n |] - -instance Lift Associativity where - lift LeftAssociative = conE 'LeftAssociative - lift RightAssociative = conE 'RightAssociative - lift NotAssociative = conE 'NotAssociative - -mkConstrInstance :: Name -> Con -> Q Dec -mkConstrInstance dt (NormalC n _) = mkConstrInstanceWith dt n [] -mkConstrInstance dt (RecC n _) = mkConstrInstanceWith dt n - [ funD 'conIsRecord [clause [wildP] (normalB (conE 'True)) []]] -mkConstrInstance dt (InfixC t1 n t2) = - do - i <- reify n - let fi = case i of - DataConI _ _ _ f -> convertFixity f - _ -> Prefix - instanceD (cxt []) (appT (conT ''Constructor) (conT $ genName [dt, n])) - [funD 'conName [clause [wildP] (normalB (stringE (nameBase n))) []], - funD 'conFixity [clause [wildP] (normalB [| fi |]) []]] - where - convertFixity (Fixity n d) = Infix (convertDirection d) n - convertDirection InfixL = LeftAssociative - convertDirection InfixR = RightAssociative - convertDirection InfixN = NotAssociative - -mkConstrInstanceWith :: Name -> Name -> [Q Dec] -> Q Dec -mkConstrInstanceWith dt n extra = - instanceD (cxt []) (appT (conT ''Constructor) (conT $ genName [dt, n])) - (funD 'conName [clause [wildP] (normalB (stringE (nameBase n))) []] : extra) - -mkSelectInstance :: Name -> Con -> Q [Dec] -mkSelectInstance dt r@(RecC n fs) = return (map one fs) where - one (f, _, _) = - InstanceD ([]) (AppT (ConT ''Selector) (ConT $ genName [dt, n, f])) - [FunD 'selName [Clause [WildP] - (NormalB (LitE (StringL (nameBase f)))) []]] -mkSelectInstance _ _ = return [] - -rep0Type :: Name -> Q Type -rep0Type n = - do - -- runIO $ putStrLn $ "processing " ++ show n - i <- reify n - let b = case i of - TyConI (DataD _ dt vs cs _) -> - (conT ''D1) `appT` (conT $ genName [dt]) `appT` - (foldr1' sum (conT ''V1) - (map (rep0Con (dt, map tyVarBndrToName vs)) cs)) - TyConI (NewtypeD _ dt vs c _) -> - (conT ''D1) `appT` (conT $ genName [dt]) `appT` - (rep0Con (dt, map tyVarBndrToName vs) c) - TyConI (TySynD t _ _) -> error "type synonym?" - _ -> error "unknown construct" - --appT b (conT $ mkName (nameBase n)) - b where - sum :: Q Type -> Q Type -> Q Type - sum a b = conT ''(:+:) `appT` a `appT` b - - -rep0Con :: (Name, [Name]) -> Con -> Q Type -rep0Con (dt, vs) (NormalC n []) = - conT ''C1 `appT` (conT $ genName [dt, n]) `appT` - (conT ''S1 `appT` conT ''NoSelector `appT` conT ''U1) -rep0Con (dt, vs) (NormalC n fs) = - conT ''C1 `appT` (conT $ genName [dt, n]) `appT` - (foldr1 prod (map (repField (dt, vs) . snd) fs)) where - prod :: Q Type -> Q Type -> Q Type - prod a b = conT ''(:*:) `appT` a `appT` b -rep0Con (dt, vs) r@(RecC n []) = - conT ''C1 `appT` (conT $ genName [dt, n]) `appT` conT ''U1 -rep0Con (dt, vs) r@(RecC n fs) = - conT ''C1 `appT` (conT $ genName [dt, n]) `appT` - (foldr1 prod (map (repField' (dt, vs) n) fs)) where - prod :: Q Type -> Q Type -> Q Type - prod a b = conT ''(:*:) `appT` a `appT` b - -rep0Con d (InfixC t1 n t2) = rep0Con d (NormalC n [t1,t2]) - ---dataDeclToType :: (Name, [Name]) -> Type ---dataDeclToType (dt, vs) = foldl (\a b -> AppT a (VarT b)) (ConT dt) vs - -repField :: (Name, [Name]) -> Type -> Q Type ---repField d t | t == dataDeclToType d = conT ''I -repField d t = conT ''S1 `appT` conT ''NoSelector `appT` - (conT ''Rec0 `appT` return t) - -repField' :: (Name, [Name]) -> Name -> (Name, Strict, Type) -> Q Type ---repField' d ns (_, _, t) | t == dataDeclToType d = conT ''I -repField' (dt, vs) ns (f, _, t) = conT ''S1 `appT` conT (genName [dt, ns, f]) - `appT` (conT ''Rec0 `appT` return t) --- Note: we should generate Par0 too, at some point - - -mkFrom :: Name -> Int -> Int -> Name -> Q [Q Clause] -mkFrom ns m i n = - do - -- runIO $ putStrLn $ "processing " ++ show n - let wrapE e = lrE m i e - i <- reify n - let b = case i of - TyConI (DataD _ dt vs cs _) -> - zipWith (fromCon wrapE ns (dt, map tyVarBndrToName vs) - (length cs)) [0..] cs - TyConI (NewtypeD _ dt vs c _) -> - [fromCon wrapE ns (dt, map tyVarBndrToName vs) 1 0 c] - TyConI (TySynD t _ _) -> error "type synonym?" - -- [clause [varP (field 0)] (normalB (wrapE $ conE 'K1 `appE` varE (field 0))) []] - _ -> error "unknown construct" - return b - -mkTo :: Name -> Int -> Int -> Name -> Q [Q Clause] -mkTo ns m i n = - do - -- runIO $ putStrLn $ "processing " ++ show n - let wrapP p = lrP m i p - i <- reify n - let b = case i of - TyConI (DataD _ dt vs cs _) -> - zipWith (toCon wrapP ns (dt, map tyVarBndrToName vs) - (length cs)) [0..] cs - TyConI (NewtypeD _ dt vs c _) -> - [toCon wrapP ns (dt, map tyVarBndrToName vs) 1 0 c] - TyConI (TySynD t _ _) -> error "type synonym?" - -- [clause [wrapP $ conP 'K1 [varP (field 0)]] (normalB $ varE (field 0)) []] - _ -> error "unknown construct" - return b - -fromCon :: (Q Exp -> Q Exp) -> Name -> (Name, [Name]) -> Int -> Int -> Con -> Q Clause -fromCon wrap ns (dt, vs) m i (NormalC cn []) = - clause - [conP cn []] - (normalB $ appE (conE 'M1) $ wrap $ lrE m i $ appE (conE 'M1) $ - conE 'M1 `appE` (conE 'U1)) [] -fromCon wrap ns (dt, vs) m i (NormalC cn fs) = - -- runIO (putStrLn ("constructor " ++ show ix)) >> - clause - [conP cn (map (varP . field) [0..length fs - 1])] - (normalB $ appE (conE 'M1) $ wrap $ lrE m i $ conE 'M1 `appE` - foldr1 prod (zipWith (fromField (dt, vs)) [0..] (map snd fs))) [] - where prod x y = conE '(:*:) `appE` x `appE` y -fromCon wrap ns (dt, vs) m i r@(RecC cn []) = - clause - [conP cn []] - (normalB $ appE (conE 'M1) $ wrap $ lrE m i $ conE 'M1 `appE` (conE 'U1)) [] -fromCon wrap ns (dt, vs) m i r@(RecC cn fs) = - clause - [conP cn (map (varP . field) [0..length fs - 1])] - (normalB $ appE (conE 'M1) $ wrap $ lrE m i $ conE 'M1 `appE` - foldr1 prod (zipWith (fromField (dt, vs)) [0..] (map trd fs))) [] - where prod x y = conE '(:*:) `appE` x `appE` y -fromCon wrap ns (dt, vs) m i (InfixC t1 cn t2) = - fromCon wrap ns (dt, vs) m i (NormalC cn [t1,t2]) - -fromField :: (Name, [Name]) -> Int -> Type -> Q Exp ---fromField (dt, vs) nr t | t == dataDeclToType (dt, vs) = conE 'I `appE` varE (field nr) -fromField (dt, vs) nr t = conE 'M1 `appE` (conE 'K1 `appE` varE (field nr)) - -toCon :: (Q Pat -> Q Pat) -> Name -> (Name, [Name]) -> Int -> Int -> Con -> Q Clause -toCon wrap ns (dt, vs) m i (NormalC cn []) = - clause - [wrap $ conP 'M1 [lrP m i $ conP 'M1 [conP 'M1 [conP 'U1 []]]]] - (normalB $ conE cn) [] -toCon wrap ns (dt, vs) m i (NormalC cn fs) = - -- runIO (putStrLn ("constructor " ++ show ix)) >> - clause - [wrap $ conP 'M1 [lrP m i $ conP 'M1 - [foldr1 prod (zipWith (toField (dt, vs)) [0..] (map snd fs))]]] - (normalB $ foldl appE (conE cn) (map (varE . field) [0..length fs - 1])) [] - where prod x y = conP '(:*:) [x,y] -toCon wrap ns (dt, vs) m i r@(RecC cn []) = - clause - [wrap $ conP 'M1 [lrP m i $ conP 'M1 [conP 'U1 []]]] - (normalB $ conE cn) [] -toCon wrap ns (dt, vs) m i r@(RecC cn fs) = - clause - [wrap $ conP 'M1 [lrP m i $ conP 'M1 - [foldr1 prod (zipWith (toField (dt, vs)) [0..] (map trd fs))]]] - (normalB $ foldl appE (conE cn) (map (varE . field) [0..length fs - 1])) [] - where prod x y = conP '(:*:) [x,y] -toCon wrap ns (dt, vs) m i (InfixC t1 cn t2) = - toCon wrap ns (dt, vs) m i (NormalC cn [t1,t2]) - -toField :: (Name, [Name]) -> Int -> Type -> Q Pat ---toField (dt, vs) nr t | t == dataDeclToType (dt, vs) = conP 'I [varP (field nr)] -toField (dt, vs) nr t = conP 'M1 [conP 'K1 [varP (field nr)]] - - -field :: Int -> Name -field n = mkName $ "f" ++ show n - -lrP :: Int -> Int -> (Q Pat -> Q Pat) -lrP 1 0 p = p -lrP m 0 p = conP 'L1 [p] -lrP m i p = conP 'R1 [lrP (m-1) (i-1) p] - -lrE :: Int -> Int -> (Q Exp -> Q Exp) -lrE 1 0 e = e -lrE m 0 e = conE 'L1 `appE` e -lrE m i e = conE 'R1 `appE` lrE (m-1) (i-1) e - -trd (_,_,c) = c - --- | Variant of foldr1 which returns a special element for empty lists -foldr1' f x [] = x -foldr1' _ _ [x] = x -foldr1' f x (h:t) = f h (foldr1' f x t) +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ViewPatterns #-}++{- |+Module : Generics.Deriving.TH+Copyright : (c) 2008--2009 Universiteit Utrecht+License : BSD3++Maintainer : generics@haskell.org+Stability : experimental+Portability : non-portable++This module contains Template Haskell code that can be used to+automatically generate the boilerplate code for the generic deriving+library.++To use these functions, pass the name of a data type as an argument:++@+{-# LANGUAGE TemplateHaskell #-}++data Example a = Example Int Char a+$('deriveAll0' ''Example) -- Derives Generic instance+$('deriveAll1' ''Example) -- Derives Generic1 instance+$('deriveAll0And1' ''Example) -- Derives Generic and Generic1 instances+@++On GHC 7.4 or later, this code can also be used with data families. To derive+for a data family instance, pass the name of one of the instance's constructors:++@+{-# LANGUAGE FlexibleInstances, TemplateHaskell, TypeFamilies #-}++data family Family a b+newtype instance Family Char x = FamilyChar Char+data instance Family Bool x = FamilyTrue | FamilyFalse++$('deriveAll0' 'FamilyChar) -- instance Generic (Family Char b) where ...+$('deriveAll1' 'FamilyTrue) -- instance Generic1 (Family Bool) where ...+-- Alternatively, one could type $(deriveAll1 'FamilyFalse)+@+-}++-- Adapted from Generics.Regular.TH+module Generics.Deriving.TH (+ -- * @derive@- functions+ deriveMeta+ , deriveData+ , deriveConstructors+ , deriveSelectors++ , deriveAll+ , deriveAll0+ , deriveAll1+ , deriveAll0And1+ , deriveRepresentable0+ , deriveRepresentable1+ , deriveRep0+ , deriveRep1++ -- * @make@- functions+ -- $make+ , makeRep0Inline+ , makeRep0+ , makeRep0FromType+ , makeFrom+ , makeFrom0+ , makeTo+ , makeTo0+ , makeRep1Inline+ , makeRep1+ , makeRep1FromType+ , makeFrom1+ , makeTo1++ -- * Options+ -- $options+ -- ** Option types+ , Options(..)+ , defaultOptions+ , RepOptions(..)+ , defaultRepOptions+ , KindSigOptions+ , defaultKindSigOptions+ , EmptyCaseOptions+ , defaultEmptyCaseOptions++ -- ** Functions with optional arguments+ , deriveAll0Options+ , deriveAll1Options+ , deriveAll0And1Options+ , deriveRepresentable0Options+ , deriveRepresentable1Options+ , deriveRep0Options+ , deriveRep1Options++ , makeFrom0Options+ , makeTo0Options+ , makeFrom1Options+ , makeTo1Options+ ) where++import Control.Monad ((>=>), unless, when)++import qualified Data.Map as Map (empty, fromList)++import Generics.Deriving.TH.Internal+import Generics.Deriving.TH.Post4_9++import Language.Haskell.TH.Datatype+import Language.Haskell.TH.Datatype.TyVarBndr+import Language.Haskell.TH.Lib+import Language.Haskell.TH++{- $options+'Options' gives you a way to further tweak derived 'Generic' and 'Generic1' instances:++* 'RepOptions': By default, all derived 'Rep' and 'Rep1' type instances emit the code+ directly (the 'InlineRep' option). One can also choose to emit a separate type+ synonym for the 'Rep' type (this is the functionality of 'deriveRep0' and+ 'deriveRep1') and define a 'Rep' instance in terms of that type synonym (the+ 'TypeSynonymRep' option).++* 'EmptyCaseOptions': By default, all derived instances for empty data types+ (i.e., data types with no constructors) use 'error' in @from(1)@/@to(1)@.+ For instance, @data Empty@ would have this derived 'Generic' instance:++ @+ instance Generic Empty where+ type Rep Empty = D1 ('MetaData ...) V1+ from _ = M1 (error "No generic representation for empty datatype Empty")+ to (M1 _) = error "No generic representation for empty datatype Empty"+ @++ This matches the behavior of GHC up until 8.4, when derived @Generic(1)@+ instances began to use the @EmptyCase@ extension. In GHC 8.4, the derived+ 'Generic' instance for @Empty@ would instead be:++ @+ instance Generic Empty where+ type Rep Empty = D1 ('MetaData ...) V1+ from x = M1 (case x of {})+ to (M1 x) = case x of {}+ @++ This is a slightly better encoding since, for example, any divergent+ computations passed to 'from' will actually diverge (as opposed to before,+ where the result would always be a call to 'error'). On the other hand, using+ this encoding in @generic-deriving@ has one large drawback: it requires+ enabling @EmptyCase@, an extension which was only introduced in GHC 7.8+ (and only received reliable pattern-match coverage checking in 8.2).++ The 'EmptyCaseOptions' field controls whether code should be emitted that+ uses @EmptyCase@ (i.e., 'EmptyCaseOptions' set to 'True') or not ('False').+ The default value is 'False'. Note that even if set to 'True', this option+ has no effect on GHCs before 7.8, as @EmptyCase@ did not exist then.++* 'KindSigOptions': By default, all derived instances will use explicit kind+ signatures (when the 'KindSigOptions' is 'True'). You might wish to set the+ 'KindSigOptions' to 'False' if you want a 'Generic'/'Generic1' instance at+ a particular kind that GHC will infer correctly, but the functions in this+ module won't guess correctly. You probably won't ever need this option+ unless you are a power user.+-}++-- | Additional options for configuring derived 'Generic'/'Generic1' instances+-- using Template Haskell.+data Options = Options+ { repOptions :: RepOptions+ , kindSigOptions :: KindSigOptions+ , emptyCaseOptions :: EmptyCaseOptions+ } deriving (Eq, Ord, Read, Show)++-- | Sensible default 'Options'.+defaultOptions :: Options+defaultOptions = Options+ { repOptions = defaultRepOptions+ , kindSigOptions = defaultKindSigOptions+ , emptyCaseOptions = defaultEmptyCaseOptions+ }++-- | Configures whether 'Rep'/'Rep1' type instances should be defined inline in a+-- derived 'Generic'/'Generic1' instance ('InlineRep') or defined in terms of a+-- type synonym ('TypeSynonymRep').+data RepOptions = InlineRep+ | TypeSynonymRep+ deriving (Eq, Ord, Read, Show)++-- | 'InlineRep', a sensible default 'RepOptions'.+defaultRepOptions :: RepOptions+defaultRepOptions = InlineRep++-- | 'True' if explicit kind signatures should be used in derived+-- 'Generic'/'Generic1' instances, 'False' otherwise.+type KindSigOptions = Bool++-- | 'True', a sensible default 'KindSigOptions'.+defaultKindSigOptions :: KindSigOptions+defaultKindSigOptions = True++-- | 'True' if generated code for empty data types should use the @EmptyCase@+-- extension, 'False' otherwise. This has no effect on GHCs before 7.8, since+-- @EmptyCase@ is only available in 7.8 or later.+type EmptyCaseOptions = Bool++-- | Sensible default 'EmptyCaseOptions'.+defaultEmptyCaseOptions :: EmptyCaseOptions+defaultEmptyCaseOptions = False++-- | A backwards-compatible synonym for 'deriveAll0'.+deriveAll :: Name -> Q [Dec]+deriveAll = deriveAll0++-- | Given the type and the name (as string) for the type to derive,+-- generate the 'Data' instance, the 'Constructor' instances, the 'Selector'+-- instances, and the 'Representable0' instance.+deriveAll0 :: Name -> Q [Dec]+deriveAll0 = deriveAll0Options defaultOptions++-- | Like 'deriveAll0', but takes an 'Options' argument.+deriveAll0Options :: Options -> Name -> Q [Dec]+deriveAll0Options = deriveAllCommon True False++-- | Given the type and the name (as string) for the type to derive,+-- generate the 'Data' instance, the 'Constructor' instances, the 'Selector'+-- instances, and the 'Representable1' instance.+deriveAll1 :: Name -> Q [Dec]+deriveAll1 = deriveAll1Options defaultOptions++-- | Like 'deriveAll1', but takes an 'Options' argument.+deriveAll1Options :: Options -> Name -> Q [Dec]+deriveAll1Options = deriveAllCommon False True++-- | Given the type and the name (as string) for the type to derive,+-- generate the 'Data' instance, the 'Constructor' instances, the 'Selector'+-- instances, the 'Representable0' instance, and the 'Representable1' instance.+deriveAll0And1 :: Name -> Q [Dec]+deriveAll0And1 = deriveAll0And1Options defaultOptions++-- | Like 'deriveAll0And1', but takes an 'Options' argument.+deriveAll0And1Options :: Options -> Name -> Q [Dec]+deriveAll0And1Options = deriveAllCommon True True++deriveAllCommon :: Bool -> Bool -> Options -> Name -> Q [Dec]+deriveAllCommon generic generic1 opts n = do+ a <- deriveMeta n+ b <- if generic+ then deriveRepresentableCommon Generic opts n+ else return []+ c <- if generic1+ then deriveRepresentableCommon Generic1 opts n+ else return []+ return (a ++ b ++ c)++-- | Given the type and the name (as string) for the Representable0 type+-- synonym to derive, generate the 'Representable0' instance.+deriveRepresentable0 :: Name -> Q [Dec]+deriveRepresentable0 = deriveRepresentable0Options defaultOptions++-- | Like 'deriveRepresentable0', but takes an 'Options' argument.+deriveRepresentable0Options :: Options -> Name -> Q [Dec]+deriveRepresentable0Options = deriveRepresentableCommon Generic++-- | Given the type and the name (as string) for the Representable1 type+-- synonym to derive, generate the 'Representable1' instance.+deriveRepresentable1 :: Name -> Q [Dec]+deriveRepresentable1 = deriveRepresentable1Options defaultOptions++-- | Like 'deriveRepresentable1', but takes an 'Options' argument.+deriveRepresentable1Options :: Options -> Name -> Q [Dec]+deriveRepresentable1Options = deriveRepresentableCommon Generic1++deriveRepresentableCommon :: GenericClass -> Options -> Name -> Q [Dec]+deriveRepresentableCommon gClass opts n = do+ rep <- if repOptions opts == InlineRep+ then return []+ else deriveRepCommon gClass (kindSigOptions opts) n+ inst <- deriveInst gClass opts n+ return (rep ++ inst)++-- | Derive only the 'Rep0' type synonym. Not needed if 'deriveRepresentable0'+-- is used.+deriveRep0 :: Name -> Q [Dec]+deriveRep0 = deriveRep0Options defaultKindSigOptions++-- | Like 'deriveRep0', but takes an 'KindSigOptions' argument.+deriveRep0Options :: KindSigOptions -> Name -> Q [Dec]+deriveRep0Options = deriveRepCommon Generic++-- | Derive only the 'Rep1' type synonym. Not needed if 'deriveRepresentable1'+-- is used.+deriveRep1 :: Name -> Q [Dec]+deriveRep1 = deriveRep1Options defaultKindSigOptions++-- | Like 'deriveRep1', but takes an 'KindSigOptions' argument.+deriveRep1Options :: KindSigOptions -> Name -> Q [Dec]+deriveRep1Options = deriveRepCommon Generic1++deriveRepCommon :: GenericClass -> KindSigOptions -> Name -> Q [Dec]+deriveRepCommon gClass useKindSigs n = do+ i <- reifyDataInfo n+ let (name, instTys, cons, dv) = either error id i+ gt = mkGenericTvbs gClass instTys+ -- See Note [Forcing buildTypeInstance]+ !_ <- buildTypeInstance gClass useKindSigs name instTys++ -- See Note [Kind signatures in derived instances]+ let tySynVars = genericInitTvbs gt+ tySynVars' = if useKindSigs+ then tySynVars+ else map unKindedTV tySynVars+ fmap (:[]) $ tySynD (genRepName gClass dv name)+ (changeTVFlags bndrReq tySynVars')+ (repType gt dv name Map.empty cons)++deriveInst :: GenericClass -> Options -> Name -> Q [Dec]+deriveInst Generic = deriveInstCommon genericTypeName repTypeName Generic fromValName toValName+deriveInst Generic1 = deriveInstCommon generic1TypeName rep1TypeName Generic1 from1ValName to1ValName++deriveInstCommon :: Name+ -> Name+ -> GenericClass+ -> Name+ -> Name+ -> Options+ -> Name+ -> Q [Dec]+deriveInstCommon genericName repName gClass fromName toName opts n = do+ i <- reifyDataInfo n+ let (name, instTys, cons, dv) = either error id i+ gt = mkGenericTvbs gClass instTys+ useKindSigs = kindSigOptions opts+ -- See Note [Forcing buildTypeInstance]+ !(origTy, origKind) <- buildTypeInstance gClass useKindSigs name instTys+ tyInsRHS <- if repOptions opts == InlineRep+ then repType gt dv name Map.empty cons+ else makeRepTySynApp gClass dv name origTy++ let origSigTy = if useKindSigs+ then SigT origTy origKind+ else origTy+ tyIns <- tySynInstDCompat repName Nothing [return origSigTy] (return tyInsRHS)+ let ecOptions = emptyCaseOptions opts+ mkBody maker = [clause []+ (normalB $+ mkCaseExp $+ maker gt ecOptions name cons)+ []]+ fcs = mkBody mkFrom+ tcs = mkBody mkTo++ inline_pragmas+ | inlining_useful cons+ = map (\fun_name ->+ pragInlD fun_name+ Inline FunLike (FromPhase 1)+ ) [fromName, toName]+ | otherwise+ = []++ fmap (:[]) $+ instanceD (cxt []) (conT genericName `appT` return origSigTy)+ (inline_pragmas ++ [return tyIns, funD fromName fcs, funD toName tcs])+ where+ -- Adapted from inlining_useful in GHC.Tc.Deriv.Generics.mkBindsRep in the+ -- GHC source code:+ --+ -- https://gitlab.haskell.org/ghc/ghc/-/blob/80729d96e47c99dc38e83612dfcfe01cf565eac0/compiler/GHC/Tc/Deriv/Generics.hs#L368-386+ inlining_useful cons+ | ncons <= 1 = True+ | ncons <= 4 = max_fields <= 5+ | ncons <= 8 = max_fields <= 2+ | ncons <= 16 = max_fields <= 1+ | ncons <= 24 = max_fields == 0+ | otherwise = False+ where+ ncons = length cons+ max_fields = maximum $ map (length . constructorFields) cons++{- $make++There are some data types for which the Template Haskell deriver functions in+this module are not sophisticated enough to infer the correct 'Generic' or+'Generic1' instances. As an example, consider this data type:++@+newtype Fix f a = Fix (f (Fix f a))+@++A proper 'Generic1' instance would look like this:++@+instance Functor f => Generic1 (Fix f) where ...+@++Unfortunately, 'deriveRepresentable1' cannot infer the @Functor f@ constraint.+One can still define a 'Generic1' instance for @Fix@, however, by using the+functions in this module that are prefixed with @make@-. For example:++@+$('deriveMeta' ''Fix)+$('deriveRep1' ''Fix)+instance Functor f => Generic1 (Fix f) where+ type Rep1 (Fix f) = $('makeRep1Inline' ''Fix [t| Fix f |])+ from1 = $('makeFrom1' ''Fix)+ to1 = $('makeTo1' ''Fix)+@++Note that due to the lack of type-level lambdas in Haskell, one must manually+apply @'makeRep1Inline' ''Fix@ to the type @Fix f@.++Be aware that there is a bug on GHC 7.0, 7.2, and 7.4 which might prevent you from+using 'makeRep0Inline' and 'makeRep1Inline'. In the @Fix@ example above, you+would experience the following error:++@+ Kinded thing `f' used as a type+ In the Template Haskell quotation [t| Fix f |]+@++Then a workaround is to use 'makeRep1' instead, which requires you to:++1. Invoke 'deriveRep1' beforehand++2. Pass as arguments the type variables that occur in the instance, in order+ from left to right, topologically sorted, excluding duplicates. (Normally,+ 'makeRep1Inline' would figure this out for you.)++Using the above example:++@+$('deriveMeta' ''Fix)+$('deriveRep1' ''Fix)+instance Functor f => Generic1 (Fix f) where+ type Rep1 (Fix f) = $('makeRep1' ''Fix) f+ from1 = $('makeFrom1' ''Fix)+ to1 = $('makeTo1' ''Fix)+@++On GHC 7.4, you might encounter more complicated examples involving data+families. For instance:++@+data family Fix a b c d+newtype instance Fix b (f c) (g b) a = Fix (f (Fix b (f c) (g b) a))++$('deriveMeta' ''Fix)+$('deriveRep1' ''Fix)+instance Functor f => Generic1 (Fix b (f c) (g b)) where+ type Rep1 (Fix b (f c) (g b)) = $('makeRep1' 'Fix) b f c g+ from1 = $('makeFrom1' 'Fix)+ to1 = $('makeTo1' 'Fix)+@++Note that you don't pass @b@ twice, only once.+-}++-- | Generates the full 'Rep' type inline. Since this type can be quite+-- large, it is recommended you only use this to define 'Rep', e.g.,+--+-- @+-- type Rep (Foo (a :: k) b) = $('makeRep0Inline' ''Foo [t| Foo (a :: k) b |])+-- @+--+-- You can then simply refer to @Rep (Foo a b)@ elsewhere.+--+-- Note that the type passed as an argument to 'makeRep0Inline' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep0Inline' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+makeRep0Inline :: Name -> Q Type -> Q Type+makeRep0Inline n = makeRepCommon Generic InlineRep n . Just++-- | Generates the full 'Rep1' type inline. Since this type can be quite+-- large, it is recommended you only use this to define 'Rep1', e.g.,+--+-- @+-- type Rep1 (Foo (a :: k)) = $('makeRep0Inline' ''Foo [t| Foo (a :: k) |])+-- @+--+-- You can then simply refer to @Rep1 (Foo a)@ elsewhere.+--+-- Note that the type passed as an argument to 'makeRep1Inline' must match the+-- type argument of 'Rep1' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep1Inline' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+makeRep1Inline :: Name -> Q Type -> Q Type+makeRep1Inline n = makeRepCommon Generic1 InlineRep n . Just++-- | Generates the 'Rep' type synonym constructor (as opposed to 'deriveRep0',+-- which generates the type synonym declaration). After splicing it into+-- Haskell source, it expects types as arguments. For example:+--+-- @+-- type Rep (Foo a b) = $('makeRep0' ''Foo) a b+-- @+--+-- The use of 'makeRep0' is generally discouraged, as it can sometimes be+-- difficult to predict the order in which you are expected to pass type+-- variables. As a result, 'makeRep0Inline' is recommended instead. However,+-- 'makeRep0Inline' is not usable on GHC 7.0, 7.2, or 7.4 due to a GHC bug,+-- so 'makeRep0' still exists for GHC 7.0, 7.2, and 7.4 users.+makeRep0 :: Name -> Q Type+makeRep0 n = makeRepCommon Generic TypeSynonymRep n Nothing++-- | Generates the 'Rep1' type synonym constructor (as opposed to 'deriveRep1',+-- which generates the type synonym declaration). After splicing it into+-- Haskell source, it expects types as arguments. For example:+--+-- @+-- type Rep1 (Foo a) = $('makeRep1' ''Foo) a+-- @+--+-- The use of 'makeRep1' is generally discouraged, as it can sometimes be+-- difficult to predict the order in which you are expected to pass type+-- variables. As a result, 'makeRep1Inline' is recommended instead. However,+-- 'makeRep1Inline' is not usable on GHC 7.0, 7.2, or 7.4 due to a GHC bug,+-- so 'makeRep1' still exists for GHC 7.0, 7.2, and 7.4 users.+makeRep1 :: Name -> Q Type+makeRep1 n = makeRepCommon Generic1 TypeSynonymRep n Nothing++-- | Generates the 'Rep' type synonym constructor (as opposed to 'deriveRep0',+-- which generates the type synonym declaration) applied to its type arguments.+-- Unlike 'makeRep0', this also takes a quoted 'Type' as an argument, e.g.,+--+-- @+-- type Rep (Foo (a :: k) b) = $('makeRep0FromType' ''Foo [t| Foo (a :: k) b |])+-- @+--+-- Note that the type passed as an argument to 'makeRep0FromType' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep0FromType' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+--+-- The use of 'makeRep0FromType' is generally discouraged, since 'makeRep0Inline'+-- does exactly the same thing but without having to go through an intermediate+-- type synonym, and as a result, 'makeRep0Inline' tends to be less buggy.+makeRep0FromType :: Name -> Q Type -> Q Type+makeRep0FromType n = makeRepCommon Generic TypeSynonymRep n . Just++-- | Generates the 'Rep1' type synonym constructor (as opposed to 'deriveRep1',+-- which generates the type synonym declaration) applied to its type arguments.+-- Unlike 'makeRep1', this also takes a quoted 'Type' as an argument, e.g.,+--+-- @+-- type Rep1 (Foo (a :: k)) = $('makeRep1FromType' ''Foo [t| Foo (a :: k) |])+-- @+--+-- Note that the type passed as an argument to 'makeRep1FromType' must match the+-- type argument of 'Rep' exactly, even up to including the explicit kind+-- signature on @a@. This is due to a limitation of Template Haskell—without+-- the kind signature, 'makeRep1FromType' has no way of figuring out the kind of+-- @a@, and the generated type might be completely wrong as a result!+--+-- The use of 'makeRep1FromType' is generally discouraged, since 'makeRep1Inline'+-- does exactly the same thing but without having to go through an intermediate+-- type synonym, and as a result, 'makeRep1Inline' tends to be less buggy.+makeRep1FromType :: Name -> Q Type -> Q Type+makeRep1FromType n = makeRepCommon Generic1 TypeSynonymRep n . Just++makeRepCommon :: GenericClass+ -> RepOptions+ -> Name+ -> Maybe (Q Type)+ -> Q Type+makeRepCommon gClass repOpts n mbQTy = do+ i <- reifyDataInfo n+ let (name, instTys, cons, dv) = either error id i+ gt = mkGenericTvbs gClass instTys+ -- See Note [Forcing buildTypeInstance]+ !_ <- buildTypeInstance gClass False name instTys++ case (mbQTy, repOpts) of+ (Just qTy, TypeSynonymRep) -> qTy >>= makeRepTySynApp gClass dv name+ (Just qTy, InlineRep) -> qTy >>= makeRepInline gt dv name cons+ (Nothing, TypeSynonymRep) -> conT $ genRepName gClass dv name+ (Nothing, InlineRep) -> fail "makeRepCommon"++makeRepInline :: GenericTvbs+ -> DatatypeVariant_+ -> Name+ -> [ConstructorInfo]+ -> Type+ -> Q Type+makeRepInline gt dv name cons ty = do+ let instVars = freeVariablesWellScoped [ty]+ tySynVars = genericInitTvbs gt++ typeSubst :: TypeSubst+ typeSubst = Map.fromList $+ zip (map tvName tySynVars)+ (map (VarT . tvName) instVars)++ repType gt dv name typeSubst cons++makeRepTySynApp :: GenericClass -> DatatypeVariant_ -> Name+ -> Type -> Q Type+makeRepTySynApp gClass dv name ty =+ -- Here, we figure out the distinct type variables (in order from left-to-right)+ -- of the LHS of the Rep(1) instance. We call unKindedTV because the kind+ -- inferencer can figure out the kinds perfectly well, so we don't need to+ -- give anything here explicit kind signatures.+ let instTvbs = map unKindedTV $ freeVariablesWellScoped [ty]+ in return $ applyTyToTvbs (genRepName gClass dv name) instTvbs++-- | A backwards-compatible synonym for 'makeFrom0'.+makeFrom :: Name -> Q Exp+makeFrom = makeFrom0++-- | Generates a lambda expression which behaves like 'from'.+makeFrom0 :: Name -> Q Exp+makeFrom0 = makeFrom0Options defaultEmptyCaseOptions++-- | Like 'makeFrom0Options', but takes an 'EmptyCaseOptions' argument.+makeFrom0Options :: EmptyCaseOptions -> Name -> Q Exp+makeFrom0Options = makeFunCommon mkFrom Generic++-- | A backwards-compatible synonym for 'makeTo0'.+makeTo :: Name -> Q Exp+makeTo = makeTo0++-- | Generates a lambda expression which behaves like 'to'.+makeTo0 :: Name -> Q Exp+makeTo0 = makeTo0Options defaultEmptyCaseOptions++-- | Like 'makeTo0Options', but takes an 'EmptyCaseOptions' argument.+makeTo0Options :: EmptyCaseOptions -> Name -> Q Exp+makeTo0Options = makeFunCommon mkTo Generic++-- | Generates a lambda expression which behaves like 'from1'.+makeFrom1 :: Name -> Q Exp+makeFrom1 = makeFrom1Options defaultEmptyCaseOptions++-- | Like 'makeFrom1Options', but takes an 'EmptyCaseOptions' argument.+makeFrom1Options :: EmptyCaseOptions -> Name -> Q Exp+makeFrom1Options = makeFunCommon mkFrom Generic1++-- | Generates a lambda expression which behaves like 'to1'.+makeTo1 :: Name -> Q Exp+makeTo1 = makeTo1Options defaultEmptyCaseOptions++-- | Like 'makeTo1Options', but takes an 'EmptyCaseOptions' argument.+makeTo1Options :: EmptyCaseOptions -> Name -> Q Exp+makeTo1Options = makeFunCommon mkTo Generic1++makeFunCommon+ :: (GenericTvbs -> EmptyCaseOptions -> Name -> [ConstructorInfo] -> Q Match)+ -> GenericClass -> EmptyCaseOptions -> Name -> Q Exp+makeFunCommon maker gClass ecOptions n = do+ i <- reifyDataInfo n+ let (name, instTys, cons, _) = either error id i+ gt = mkGenericTvbs gClass instTys+ -- See Note [Forcing buildTypeInstance]+ buildTypeInstance gClass False name instTys+ `seq` mkCaseExp (maker gt ecOptions name cons)++genRepName :: GenericClass -> DatatypeVariant_+ -> Name -> Name+genRepName gClass dv n+ = mkName+ . showsDatatypeVariant dv+ . (("Rep" ++ show (fromEnum gClass)) ++)+ . ((showNameQual n ++ "_") ++)+ . sanitizeName+ $ nameBase n++repType :: GenericTvbs+ -> DatatypeVariant_+ -> Name+ -> TypeSubst+ -> [ConstructorInfo]+ -> Q Type+repType gt dv dt typeSubst cs =+ conT d1TypeName `appT` mkMetaDataType dv dt `appT`+ foldBal sum' (conT v1TypeName) (map (repCon gt dv dt typeSubst) cs)+ where+ sum' :: Q Type -> Q Type -> Q Type+ sum' a b = conT sumTypeName `appT` a `appT` b++repCon :: GenericTvbs+ -> DatatypeVariant_+ -> Name+ -> TypeSubst+ -> ConstructorInfo+ -> Q Type+repCon gt dv dt typeSubst+ (ConstructorInfo { constructorName = n+ , constructorVars = vars+ , constructorContext = ctxt+ , constructorStrictness = bangs+ , constructorFields = ts+ , constructorVariant = cv+ }) = do+ checkExistentialContext n vars ctxt+ let mbSelNames = case cv of+ NormalConstructor -> Nothing+ InfixConstructor -> Nothing+ RecordConstructor selNames -> Just selNames+ isRecord = case cv of+ NormalConstructor -> False+ InfixConstructor -> False+ RecordConstructor _ -> True+ isInfix = case cv of+ NormalConstructor -> False+ InfixConstructor -> True+ RecordConstructor _ -> False+ ssis <- reifySelStrictInfo n bangs+ repConWith gt dv dt n typeSubst mbSelNames ssis ts isRecord isInfix++repConWith :: GenericTvbs+ -> DatatypeVariant_+ -> Name+ -> Name+ -> TypeSubst+ -> Maybe [Name]+ -> [SelStrictInfo]+ -> [Type]+ -> Bool+ -> Bool+ -> Q Type+repConWith gt dv dt n typeSubst mbSelNames ssis ts isRecord isInfix = do+ let structureType :: Q Type+ structureType = foldBal prodT (conT u1TypeName) f++ f :: [Q Type]+ f = case mbSelNames of+ Just selNames -> zipWith3 (repField gt dv dt n typeSubst . Just)+ selNames ssis ts+ Nothing -> zipWith (repField gt dv dt n typeSubst Nothing)+ ssis ts++ conT c1TypeName+ `appT` mkMetaConsType dv dt n isRecord isInfix+ `appT` structureType++prodT :: Q Type -> Q Type -> Q Type+prodT a b = conT productTypeName `appT` a `appT` b++repField :: GenericTvbs+ -> DatatypeVariant_+ -> Name+ -> Name+ -> TypeSubst+ -> Maybe Name+ -> SelStrictInfo+ -> Type+ -> Q Type+repField gt dv dt ns typeSubst mbF ssi t =+ conT s1TypeName+ `appT` mkMetaSelType dv dt ns mbF ssi+ `appT` (repFieldArg gt =<< resolveTypeSynonyms t'')+ where+ -- See Note [Generic1 is polykinded in base-4.10]+ t', t'' :: Type+ t' = case gt of+ Gen1{gen1LastTvbKindVar = Just _kvName} ->+#if MIN_VERSION_base(4,10,0)+ t+#else+ substNameWithKind _kvName starK t+#endif+ _ -> t+ t'' = applySubstitution typeSubst t'++repFieldArg :: GenericTvbs -> Type -> Q Type+repFieldArg Gen0{} t = boxT t+repFieldArg (Gen1{gen1LastTvbName = name}) (dustOff -> t0) =+ go t0 >>= \res -> case res of+ NoPar -> boxT t0+ ArgRes _ r -> return r+ where+ -- | Returns NoPar if the parameter doesn't appear.+ -- Expects its argument to have been dusted.+ go :: Type -> Q (ArgRes Type)+ go ForallT{} = rankNError+#if MIN_VERSION_template_haskell(2,16,0)+ go ForallVisT{} = rankNError+#endif+ go (VarT t) | t == name = ArgRes True `fmap` conT par1TypeName+ go (AppT f x) = do+ when (not (f `ground` name)) outOfPlaceTyVarError+ mxr <- go (dustOff x)+ case mxr of+ NoPar -> return NoPar+ ArgRes arg_is_param xr -> do+ itf <- isUnsaturatedType f+ when itf typeFamilyApplicationError+ ArgRes False `fmap`+ if arg_is_param+ then+ conT rec1TypeName `appT` return f+ else+ conT composeTypeName `appT` return f `appT` return xr+ go _ = return NoPar++-- | The result of checking the argument. This NoPar+-- means the parameter wasn't there. The Bool is True+-- if the argument *is* the parameter, and False otherwise.+data ArgRes a = NoPar | ArgRes !Bool a++boxT :: Type -> Q Type+boxT ty = case unboxedRepNames ty of+ Just (boxTyName, _, _) -> conT boxTyName+ Nothing -> conT rec0TypeName `appT` return ty++mkCaseExp :: Q Match -> Q Exp+mkCaseExp qMatch = do+ val <- newName "val"+ lam1E (varP val) $ caseE (varE val) [qMatch]++mkFrom :: GenericTvbs -> EmptyCaseOptions -> Name+ -> [ConstructorInfo] -> Q Match+mkFrom gt ecOptions dt cs = do+ y <- newName "y"+ match (varP y)+ (normalB $ conE m1DataName `appE` caseE (varE y) cases)+ []+ where+ cases = case cs of+ [] -> errorFrom ecOptions dt+ _ -> zipWith (fromCon gt id (length cs)) [1..] cs++errorFrom :: EmptyCaseOptions -> Name -> [Q Match]+errorFrom useEmptyCase dt+ | useEmptyCase+ = []+ | otherwise+ = [do z <- newName "z"+ match+ (varP z)+ (normalB $+ appE (varE seqValName) (varE z) `appE`+ appE (varE errorValName)+ (stringE $ "No generic representation for empty datatype "+ ++ nameBase dt))+ []]++mkTo :: GenericTvbs -> EmptyCaseOptions -> Name+ -> [ConstructorInfo] -> Q Match+mkTo gt ecOptions dt cs = do+ y <- newName "y"+ match (conP m1DataName [varP y])+ (normalB $ caseE (varE y) cases)+ []+ where+ cases = case cs of+ [] -> errorTo ecOptions dt+ _ -> zipWith (toCon gt id (length cs)) [1..] cs++errorTo :: EmptyCaseOptions -> Name -> [Q Match]+errorTo useEmptyCase dt+ | useEmptyCase+ = []+ | otherwise+ = [do z <- newName "z"+ match+ (varP z)+ (normalB $+ appE (varE seqValName) (varE z) `appE`+ appE (varE errorValName)+ (stringE $ "No values for empty datatype " ++ nameBase dt))+ []]++fromCon :: GenericTvbs -> (Q Exp -> Q Exp) -> Int -> Int+ -> ConstructorInfo -> Q Match+fromCon gt wrap m i+ (ConstructorInfo { constructorName = cn+ , constructorVars = vars+ , constructorContext = ctxt+ , constructorFields = ts+ }) = do+ checkExistentialContext cn vars ctxt+ fNames <- newNameList "f" $ length ts+ match (conP cn (map varP fNames))+ (normalB $ wrap $ lrE i m $ conE m1DataName `appE`+ foldBal prodE (conE u1DataName) (zipWith (fromField gt) fNames ts)) []++prodE :: Q Exp -> Q Exp -> Q Exp+prodE x y = conE productDataName `appE` x `appE` y++fromField :: GenericTvbs -> Name -> Type -> Q Exp+fromField gt nr t = conE m1DataName `appE` (fromFieldWrap gt nr =<< resolveTypeSynonyms t)++fromFieldWrap :: GenericTvbs -> Name -> Type -> Q Exp+fromFieldWrap _ _ ForallT{} = rankNError+fromFieldWrap gt nr (SigT t _) = fromFieldWrap gt nr t+fromFieldWrap Gen0{} nr t = conE (boxRepName t) `appE` varE nr+fromFieldWrap (Gen1{gen1LastTvbName = name}) nr t = wC t name `appE` varE nr++wC :: Type -> Name -> Q Exp+wC (dustOff -> t0) name =+ go t0 >>= \res -> case res of+ NoPar -> conE $ boxRepName t0+ ArgRes _ r -> return r+ where+ -- | Returns NoPar if the parameter doesn't appear.+ -- Expects its argument to have been dusted.+ go :: Type -> Q (ArgRes Exp)+ go ForallT{} = rankNError+#if MIN_VERSION_template_haskell(2,16,0)+ go ForallVisT{} = rankNError+#endif+ go (VarT t) | t == name = ArgRes True `fmap` conE par1DataName+ go (AppT f x) = do+ when (not (f `ground` name)) outOfPlaceTyVarError+ mxr <- go (dustOff x)+ case mxr of+ NoPar -> return NoPar+ ArgRes arg_is_param xr -> do+ itf <- isUnsaturatedType f+ when itf typeFamilyApplicationError+ ArgRes False `fmap`+ if arg_is_param+ then+ conE rec1DataName+ else+ infixApp (conE comp1DataName) (varE composeValName) (varE fmapValName `appE` return xr)+ go _ = return NoPar++boxRepName :: Type -> Name+boxRepName = maybe k1DataName snd3 . unboxedRepNames++toCon :: GenericTvbs -> (Q Pat -> Q Pat) -> Int -> Int+ -> ConstructorInfo -> Q Match+toCon gt wrap m i+ (ConstructorInfo { constructorName = cn+ , constructorVars = vars+ , constructorContext = ctxt+ , constructorFields = ts+ }) = do+ checkExistentialContext cn vars ctxt+ fNames <- newNameList "f" $ length ts+ match (wrap $ lrP i m $ conP m1DataName+ [foldBal prod (conP u1DataName []) (zipWith (toField gt) fNames ts)])+ (normalB $ foldl appE (conE cn)+ (zipWith (\nr -> resolveTypeSynonyms >=> toConUnwC gt nr)+ fNames ts)) []+ where prod x y = conP productDataName [x,y]++toConUnwC :: GenericTvbs -> Name -> Type -> Q Exp+toConUnwC Gen0{} nr _ = varE nr+toConUnwC (Gen1{gen1LastTvbName = name}) nr t = unwC t name `appE` varE nr++toField :: GenericTvbs -> Name -> Type -> Q Pat+toField gt nr t = conP m1DataName [toFieldWrap gt nr t]++toFieldWrap :: GenericTvbs -> Name -> Type -> Q Pat+toFieldWrap Gen0{} nr t = conP (boxRepName t) [varP nr]+toFieldWrap Gen1{} nr _ = varP nr++unwC :: Type -> Name -> Q Exp+unwC (dustOff -> t0) name =+ go t0 >>= \res -> case res of+ NoPar -> varE $ unboxRepName t0+ ArgRes _ r -> return r+ where+ -- | Returns NoPar if the parameter doesn't appear.+ -- Expects its argument to have been dusted.+ go :: Type -> Q (ArgRes Exp)+ go ForallT{} = rankNError+#if MIN_VERSION_template_haskell(2,16,0)+ go ForallVisT{} = rankNError+#endif+ go (VarT t) | t == name = ArgRes True `fmap` varE unPar1ValName+ go (AppT f x) = do+ when (not (f `ground` name)) outOfPlaceTyVarError+ mxr <- go (dustOff x)+ case mxr of+ NoPar -> return NoPar+ ArgRes arg_is_param xr -> do+ itf <- isUnsaturatedType f+ when itf typeFamilyApplicationError+ ArgRes False `fmap`+ if arg_is_param+ then+ varE unRec1ValName+ else+ infixApp (varE fmapValName `appE` return xr)+ (varE composeValName)+ (varE unComp1ValName)+ go _ = return NoPar++unboxRepName :: Type -> Name+unboxRepName = maybe unK1ValName trd3 . unboxedRepNames++lrP :: Int -> Int -> (Q Pat -> Q Pat)+lrP i n p+ | n == 0 = fail "lrP: impossible"+ | n == 1 = p+ | i <= div n 2 = conP l1DataName [lrP i (div n 2) p]+ | otherwise = conP r1DataName [lrP (i-m) (n-m) p]+ where m = div n 2++lrE :: Int -> Int -> (Q Exp -> Q Exp)+lrE i n e+ | n == 0 = fail "lrE: impossible"+ | n == 1 = e+ | i <= div n 2 = conE l1DataName `appE` lrE i (div n 2) e+ | otherwise = conE r1DataName `appE` lrE (i-m) (n-m) e+ where m = div n 2++unboxedRepNames :: Type -> Maybe (Name, Name, Name)+unboxedRepNames ty+ | ty == ConT addrHashTypeName = Just (uAddrTypeName, uAddrDataName, uAddrHashValName)+ | ty == ConT charHashTypeName = Just (uCharTypeName, uCharDataName, uCharHashValName)+ | ty == ConT doubleHashTypeName = Just (uDoubleTypeName, uDoubleDataName, uDoubleHashValName)+ | ty == ConT floatHashTypeName = Just (uFloatTypeName, uFloatDataName, uFloatHashValName)+ | ty == ConT intHashTypeName = Just (uIntTypeName, uIntDataName, uIntHashValName)+ | ty == ConT wordHashTypeName = Just (uWordTypeName, uWordDataName, uWordHashValName)+ | otherwise = Nothing++-- For the given Types, deduces the instance type (and kind) to use for a+-- Generic(1) instance. Coming up with the instance type isn't as simple as+-- dropping the last types, as you need to be wary of kinds being instantiated+-- with *.+-- See Note [Type inference in derived instances]+buildTypeInstance :: GenericClass+ -- ^ Generic or Generic1+ -> KindSigOptions+ -- ^ Whether or not to use explicit kind signatures in the instance type+ -> Name+ -- ^ The type constructor or data family name+ -> [Type]+ -- ^ The types to instantiate the instance with+ -> Q (Type, Kind)+buildTypeInstance gClass useKindSigs tyConName varTysOrig = do+ -- Make sure to expand through type/kind synonyms! Otherwise, the+ -- eta-reduction check might get tripped up over type variables in a+ -- synonym that are actually dropped.+ -- (See GHC Trac #11416 for a scenario where this actually happened.)+ varTysExp <- mapM resolveTypeSynonyms varTysOrig++ let remainingLength :: Int+ remainingLength = length varTysOrig - fromEnum gClass++#if !(MIN_VERSION_base(4,10,0))+ droppedTysExp :: [Type]+ droppedTysExp = drop remainingLength varTysExp++ droppedStarKindStati :: [StarKindStatus]+ droppedStarKindStati = map canRealizeKindStar droppedTysExp+#endif++ -- Check that:+ --+ -- 1. There are enough types to drop+ --+ -- 2. If using GHC 8.0 or earlier, all types are either of kind * or kind k+ -- (for some kind variable k). See Note [Generic1 is polykinded in base-4.10].+ --+ -- If either of these checks fail, throw an error.+ when (remainingLength < 0+#if !(MIN_VERSION_base(4,10,0))+ || any (== OtherKind) droppedStarKindStati+#endif+ ) $+ derivingKindError tyConName++ -- Substitute kind * for any dropped kind variables+ let varTysExpSubst :: [Type]+-- See Note [Generic1 is polykinded in base-4.10]+#if MIN_VERSION_base(4,10,0)+ varTysExpSubst = varTysExp+#else+ varTysExpSubst = map (substNamesWithKindStar droppedKindVarNames) varTysExp++ droppedKindVarNames :: [Name]+ droppedKindVarNames = catKindVarNames droppedStarKindStati+#endif++ let remainingTysExpSubst, droppedTysExpSubst :: [Type]+ (remainingTysExpSubst, droppedTysExpSubst) =+ splitAt remainingLength varTysExpSubst++-- See Note [Generic1 is polykinded in base-4.10]+#if !(MIN_VERSION_base(4,10,0))+ -- If any of the dropped types were polykinded, ensure that there are of+ -- kind * after substituting * for the dropped kind variables. If not,+ -- throw an error.+ unless (all hasKindStar droppedTysExpSubst) $+ derivingKindError tyConName+#endif++ -- We now substitute all of the specialized-to-* kind variable names+ -- with *, but in the original types, not the synonym-expanded types. The reason+ -- we do this is a superficial one: we want the derived instance to resemble+ -- the datatype written in source code as closely as possible. For example,+ -- for the following data family instance:+ --+ -- data family Fam a+ -- newtype instance Fam String = Fam String+ --+ -- We'd want to generate the instance:+ --+ -- instance C (Fam String)+ --+ -- Not:+ --+ -- instance C (Fam [Char])+ let varTysOrigSubst :: [Type]+ varTysOrigSubst =+-- See Note [Generic1 is polykinded in base-4.10]+#if MIN_VERSION_base(4,10,0)+ id+#else+ map (substNamesWithKindStar droppedKindVarNames)+#endif+ $ varTysOrig++ remainingTysOrigSubst, droppedTysOrigSubst :: [Type]+ (remainingTysOrigSubst, droppedTysOrigSubst) =+ splitAt remainingLength varTysOrigSubst++ remainingTysOrigSubst' :: [Type]+ -- See Note [Kind signatures in derived instances] for an explanation+ -- of the useKindSigs check.+ remainingTysOrigSubst' =+ if useKindSigs+ then remainingTysOrigSubst+ else map unSigT remainingTysOrigSubst++ instanceType :: Type+ instanceType = applyTyToTys (ConT tyConName) remainingTysOrigSubst'++ -- See Note [Kind signatures in derived instances]+ instanceKind :: Kind+ instanceKind = makeFunKind (map typeKind droppedTysOrigSubst) starK++ -- Ensure the dropped types can be safely eta-reduced. Otherwise,+ -- throw an error.+ unless (canEtaReduce remainingTysExpSubst droppedTysExpSubst) $+ etaReductionError instanceType+ return (instanceType, instanceKind)++{-+Note [Forcing buildTypeInstance]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Sometimes, we don't explicitly need to generate a Generic(1) type instance, but+we force buildTypeInstance nevertheless. This is because it performs some checks+for whether or not the provided datatype can actually have Generic(1) implemented for+it, and produces errors if it can't. Otherwise, laziness would cause these checks+to be skipped entirely, which could result in some indecipherable type errors+down the road.++Note [Kind signatures in derived instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++We generally include explicit type signatures in derived instances. One reason for+doing so is that in the case of certain data family instances, not including kind+signatures can result in ambiguity. For example, consider the following two data+family instances that are distinguished by their kinds:++ data family Fam (a :: k)+ data instance Fam (a :: * -> *)+ data instance Fam (a :: *)++If we dropped the kind signature for a in a derived instance for Fam a, then GHC+would have no way of knowing which instance we are talking about.++In addition to using explicit kind signatures in the instance head, we also put+explicit kinds in the associated Rep(1) instance. For example, this data type:++ data S (a :: k) = S k++Will have the following Generic1 instance generated for it:++ instance Generic1 (S :: k -> *) where+ type Rep1 (S :: k -> *) = ... (Rec0 k)++Why do we do this? Imagine what the instance would be without the explicit kind+annotation in the Rep1 instance:++ instance Generic1 S where+ type Rep1 S = ... (Rec0 k)++This is an error, since the variable k is now out-of-scope!++In the rare event that attaching explicit kind annotations does the wrong+thing, there are variants of the TH functions that allow configuring the+KindSigOptions. If KindSigOptions is set to False, then generated instances+will not include explicit kind signatures, leaving it up to GHC's kind+inference machinery to figure out the correct kinds.++Note [Generic1 is polykinded in base-4.10]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Prior to base-4.10, Generic1 :: (* -> *) -> Constraint. This means that if a Generic1+instance is defined for a polykinded data type like so:++ data Proxy k (a :: k) = Proxy++Then k is unified with *, and this has an effect on the generated Generic1 instance:++ instance Generic1 (Proxy *) where ...++We must take great care to ensure that all occurrences of k are substituted with *,+or else the generated instance will be ill kinded.++In base-4.10 and later, Generic1 :: (k -> *) -> Constraint. This means we don't have+to do any of this kind unification trickery anymore! Hooray!+-}
+ src/Generics/Deriving/TH/Internal.hs view
@@ -0,0 +1,830 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++{- |+Module : Generics.Deriving.TH.Internal+Copyright : (c) 2008--2009 Universiteit Utrecht+License : BSD3++Maintainer : generics@haskell.org+Stability : experimental+Portability : non-portable++Template Haskell-related utilities.+-}++module Generics.Deriving.TH.Internal where++import Control.Monad (unless)++import Data.Char (isAlphaNum, ord)+import Data.Foldable (foldr')+import qualified Data.List as List+import qualified Data.Map as Map+import Data.Map as Map (Map)+import Data.Maybe (mapMaybe)+import qualified Data.Set as Set+import Data.Set (Set)++import qualified Generics.Deriving as GD+import Generics.Deriving hiding+ ( DecidedStrictness(..), Fixity(Infix)+ , SourceStrictness(..), SourceUnpackedness(..)+ , datatypeName+ )++import GHC.Exts (Addr#, Char#, Double#, Float#, Int#, Word#)++import Language.Haskell.TH.Datatype as Datatype+import Language.Haskell.TH.Datatype.TyVarBndr+import Language.Haskell.TH.Lib+import Language.Haskell.TH.Ppr (pprint)+import Language.Haskell.TH.Syntax++-------------------------------------------------------------------------------+-- Expanding type synonyms+-------------------------------------------------------------------------------++type TypeSubst = Map Name Type++applySubstitutionKind :: Map Name Kind -> Type -> Type+applySubstitutionKind = applySubstitution++substNameWithKind :: Name -> Kind -> Type -> Type+substNameWithKind n k = applySubstitutionKind (Map.singleton n k)++substNamesWithKindStar :: [Name] -> Type -> Type+substNamesWithKindStar ns t = foldr' (flip substNameWithKind starK) t ns++-------------------------------------------------------------------------------+-- StarKindStatus+-------------------------------------------------------------------------------++-- | Whether a type is of kind @*@, a kind variable, or some other kind. The+-- kind variable case is given special treatment solely to support GHC 8.0 and+-- earlier, in which Generic1 was not poly-kinded. In order to support deriving+-- Generic1 instances on these versions of GHC, we must substitute such kinds+-- with @*@ to ensure that the resulting instance is well kinded.+-- See @Note [Generic1 is polykinded in base-4.10]@ in "Generics.Deriving.TH".+data StarKindStatus = KindStar+ | IsKindVar Name+ | OtherKind+ deriving Eq++-- | Does a Type have kind * or k (for some kind variable k)?+canRealizeKindStar :: Type -> StarKindStatus+canRealizeKindStar t+ | hasKindStar t = KindStar+ | otherwise = case t of+ SigT _ (VarT k) -> IsKindVar k+ _ -> OtherKind++-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.+-- Otherwise, returns 'Nothing'.+starKindStatusToName :: StarKindStatus -> Maybe Name+starKindStatusToName (IsKindVar n) = Just n+starKindStatusToName _ = Nothing++-- | Concat together all of the StarKindStatuses that are IsKindVar and extract+-- the kind variables' Names out.+catKindVarNames :: [StarKindStatus] -> [Name]+catKindVarNames = mapMaybe starKindStatusToName++-------------------------------------------------------------------------------+-- Assorted utilities+-------------------------------------------------------------------------------++-- | Returns True if a Type has kind *.+hasKindStar :: Type -> Bool+hasKindStar VarT{} = True+hasKindStar (SigT _ StarT) = True+hasKindStar _ = False++-- | Converts a VarT or a SigT into Just the corresponding TyVarBndr.+-- Converts other Types to Nothing.+typeToTyVarBndr :: Type -> Maybe TyVarBndrUnit+typeToTyVarBndr (VarT n) = Just (plainTV n)+typeToTyVarBndr (SigT (VarT n) k) = Just (kindedTV n k)+typeToTyVarBndr _ = Nothing++-- | If a Type is a SigT, returns its kind signature. Otherwise, return *.+typeKind :: Type -> Kind+typeKind (SigT _ k) = k+typeKind _ = starK++-- | Turns+--+-- @+-- [a, b] c+-- @+--+-- into+--+-- @+-- a -> b -> c+-- @+makeFunType :: [Type] -> Type -> Type+makeFunType argTys resTy = foldr' (AppT . AppT ArrowT) resTy argTys++-- | Turns+--+-- @+-- [k1, k2] k3+-- @+--+-- into+--+-- @+-- k1 -> k2 -> k3+-- @+makeFunKind :: [Kind] -> Kind -> Kind+makeFunKind = makeFunType++-- | Remove any outer `SigT` and `ParensT` constructors, and turn+-- an outermost `InfixT` constructor into plain applications.+dustOff :: Type -> Type+dustOff (SigT ty _) = dustOff ty+dustOff (ParensT ty) = dustOff ty+dustOff (InfixT ty1 n ty2) = ConT n `AppT` ty1 `AppT` ty2+dustOff ty = ty++-- | Checks whether a type is an unsaturated type family+-- application.+isUnsaturatedType :: Type -> Q Bool+isUnsaturatedType = go 0 . dustOff+ where+ -- Expects its argument to be dusted+ go :: Int -> Type -> Q Bool+ go d t = case t of+ ConT tcName -> check d tcName+ AppT f _ -> go (d + 1) (dustOff f)+ _ -> return False++ check :: Int -> Name -> Q Bool+ check d tcName = do+ mbinders <- getTypeFamilyBinders tcName+ return $ case mbinders of+ Just bndrs -> length bndrs > d+ Nothing -> False++-- | Given a name, check if that name is a type family. If+-- so, return a list of its binders.+getTypeFamilyBinders :: Name -> Q (Maybe [TyVarBndrVis])+getTypeFamilyBinders tcName = do+ info <- reify tcName+ return $ case info of+ FamilyI (OpenTypeFamilyD (TypeFamilyHead _ bndrs _ _)) _+ -> Just bndrs+ FamilyI (ClosedTypeFamilyD (TypeFamilyHead _ bndrs _ _) _) _+ -> Just bndrs+ _ -> Nothing++-- | True if the type does not mention the Name+ground :: Type -> Name -> Bool+ground ty name = name `notElem` freeVariables ty++-- | Construct a type via curried application.+applyTyToTys :: Type -> [Type] -> Type+applyTyToTys = List.foldl' AppT++-- | Apply a type constructor name to type variable binders.+applyTyToTvbs :: Name -> [TyVarBndr_ flag] -> Type+applyTyToTvbs = List.foldl' (\a -> AppT a . tyVarBndrToType) . ConT++-- | Split a type signature by the arrows on its spine. For example, this:+--+-- @+-- forall a b. (a -> b) -> Char -> ()+-- @+--+-- would split to this:+--+-- @+-- ([a, b], [a -> b, Char, ()])+-- @+uncurryTy :: Type -> ([TyVarBndrSpec], [Type])+uncurryTy (AppT (AppT ArrowT t1) t2) =+ let (tvbs, tys) = uncurryTy t2+ in (tvbs, t1:tys)+uncurryTy (SigT t _) = uncurryTy t+uncurryTy (ForallT tvbs _ t) =+ let (tvbs', tys) = uncurryTy t+ in (tvbs ++ tvbs', tys)+uncurryTy t = ([], [t])++-- | Like uncurryType, except on a kind level.+uncurryKind :: Kind -> ([TyVarBndrSpec], [Kind])+uncurryKind = uncurryTy++tyVarBndrToType :: TyVarBndr_ flag -> Type+tyVarBndrToType = elimTV VarT (\n k -> SigT (VarT n) k)++-- | Generate a list of fresh names with a common prefix, and numbered suffixes.+newNameList :: String -> Int -> Q [Name]+newNameList prefix n = mapM (newName . (prefix ++) . show) [1..n]++-- | Checks to see if the last types in a data family instance can be safely eta-+-- reduced (i.e., dropped), given the other types. This checks for three conditions:+--+-- (1) All of the dropped types are type variables+-- (2) All of the dropped types are distinct+-- (3) None of the remaining types mention any of the dropped types+canEtaReduce :: [Type] -> [Type] -> Bool+canEtaReduce remaining dropped =+ all isTyVar dropped+ -- Make sure not to pass something of type [Type], since Type+ -- didn't have an Ord instance until template-haskell-2.10.0.0+ && allDistinct droppedNames+ && not (any (`mentionsName` droppedNames) remaining)+ where+ droppedNames :: [Name]+ droppedNames = map varTToName dropped++-- | Extract the Name from a type variable. If the argument Type is not a+-- type variable, throw an error.+varTToName :: Type -> Name+varTToName (VarT n) = n+varTToName (SigT t _) = varTToName t+varTToName _ = error "Not a type variable!"++-- | Is the given type a variable?+isTyVar :: Type -> Bool+isTyVar VarT{} = True+isTyVar (SigT t _) = isTyVar t+isTyVar _ = False++-- | Is the given kind a variable?+isKindVar :: Kind -> Bool+isKindVar = isTyVar++-- | Returns 'True' is a 'Type' contains no type variables.+isTypeMonomorphic :: Type -> Bool+isTypeMonomorphic = go+ where+ go :: Type -> Bool+ go (AppT t1 t2) = go t1 && go t2+ go (SigT t k) = go t && go k+ go VarT{} = False+ go _ = True++-- | Peel off a kind signature from a Type (if it has one).+unSigT :: Type -> Type+unSigT (SigT t _) = t+unSigT t = t++-- | Peel off a kind signature from a TyVarBndr (if it has one).+unKindedTV :: TyVarBndrUnit -> TyVarBndrUnit+unKindedTV tvb = elimTV (\_ -> tvb) (\n _ -> plainTV n) tvb++-- | Does the given type mention any of the Names in the list?+mentionsName :: Type -> [Name] -> Bool+mentionsName = go+ where+ go :: Type -> [Name] -> Bool+ go (AppT t1 t2) names = go t1 names || go t2 names+ go (SigT t k) names = go t names || go k names+ go (VarT n) names = n `elem` names+ go _ _ = False++-- | Are all of the items in a list (which have an ordering) distinct?+--+-- This uses Set (as opposed to nub) for better asymptotic time complexity.+allDistinct :: Ord a => [a] -> Bool+allDistinct = allDistinct' Set.empty+ where+ allDistinct' :: Ord a => Set a -> [a] -> Bool+ allDistinct' uniqs (x:xs)+ | x `Set.member` uniqs = False+ | otherwise = allDistinct' (Set.insert x uniqs) xs+ allDistinct' _ _ = True++fst3 :: (a, b, c) -> a+fst3 (a, _, _) = a++snd3 :: (a, b, c) -> b+snd3 (_, b, _) = b++trd3 :: (a, b, c) -> c+trd3 (_, _, c) = c++shrink :: (a, b, c) -> (b, c)+shrink (_, b, c) = (b, c)++foldBal :: (a -> a -> a) -> a -> [a] -> a+{-# INLINE foldBal #-} -- inlined to produce specialised code for each op+foldBal op0 x0 xs0 = fold_bal op0 x0 (length xs0) xs0+ where+ fold_bal op x !n xs = case xs of+ [] -> x+ [a] -> a+ _ -> let !nl = n `div` 2+ !nr = n - nl+ (l,r) = splitAt nl xs+ in fold_bal op x nl l+ `op` fold_bal op x nr r++isNewtypeVariant :: DatatypeVariant_ -> Bool+isNewtypeVariant Datatype_ = False+isNewtypeVariant Newtype_ = True+isNewtypeVariant (DataInstance_ {}) = False+isNewtypeVariant (NewtypeInstance_ {}) = True++-- | Indicates whether Generic or Generic1 is being derived.+data GenericClass = Generic | Generic1 deriving Enum++-- | Records information about the type variables of a data type with a+-- 'Generic' or 'Generic1' instance.+data GenericTvbs+ -- | Information about a data type with a 'Generic' instance.+ = Gen0+ { gen0Tvbs :: [TyVarBndrUnit]+ -- ^ All of the type variable arguments to the data type.+ }+ -- | Information about a data type with a 'Generic1' instance.+ | Gen1+ { gen1InitTvbs :: [TyVarBndrUnit]+ -- ^ All of the type variable arguments to the data type except the+ -- last one. In a @'Generic1' (T a_1 ... a_(n-1))@ instance, the+ -- 'gen1InitTvbs' would be @[a_1, ..., a_(n-1)]@.+ , gen1LastTvbName :: Name+ -- ^ The name of the last type variable argument to the data type.+ -- In a @'Generic1' (T a_1 ... a_(n-1))@ instance, the+ -- 'gen1LastTvbName' name would be @a_n@.+ , gen1LastTvbKindVar :: Maybe Name+ -- ^ If the 'gen1LastTvbName' has kind @k@, where @k@ is some kind+ -- variable, then the 'gen1LastTvbKindVar' is @'Just' k@. Otherwise,+ -- the 'gen1LastTvbKindVar' is 'Nothing'.+ }++-- | Compute 'GenericTvbs' from a 'GenericClass' and the type variable+-- arguments to a data type.+mkGenericTvbs :: GenericClass -> [Type] -> GenericTvbs+mkGenericTvbs gClass tySynVars =+ case gClass of+ Generic -> Gen0{gen0Tvbs = freeVariablesWellScoped tySynVars}+ Generic1 -> Gen1{ gen1InitTvbs = freeVariablesWellScoped initArgs+ , gen1LastTvbName = varTToName lastArg+ , gen1LastTvbKindVar = mbLastArgKindName+ }+ where+ -- Everything below is only used for Generic1.+ initArgs :: [Type]+ initArgs = init tySynVars++ lastArg :: Type+ lastArg = last tySynVars++ mbLastArgKindName :: Maybe Name+ mbLastArgKindName = starKindStatusToName+ $ canRealizeKindStar lastArg++-- | Return the type variable arguments to a data type that appear in a+-- 'Generic' or 'Generic1' instance. For a 'Generic' instance, this consists of+-- all the type variable arguments. For a 'Generic1' instance, this consists of+-- all the type variable arguments except for the last one.+genericInitTvbs :: GenericTvbs -> [TyVarBndrUnit]+genericInitTvbs (Gen0{gen0Tvbs = tvbs}) = tvbs+genericInitTvbs (Gen1{gen1InitTvbs = tvbs}) = tvbs++-- | A version of 'DatatypeVariant' in which the data family instance+-- constructors come equipped with the 'ConstructorInfo' of the first+-- constructor in the family instance (for 'Name' generation purposes).+data DatatypeVariant_+ = Datatype_+ | Newtype_+ | DataInstance_ ConstructorInfo+ | NewtypeInstance_ ConstructorInfo++showsDatatypeVariant :: DatatypeVariant_ -> ShowS+showsDatatypeVariant variant = (++ '_':label)+ where+ dataPlain :: String+ dataPlain = "Plain"++ dataFamily :: ConstructorInfo -> String+ dataFamily con = "Family_" ++ sanitizeName (nameBase $ constructorName con)++ label :: String+ label = case variant of+ Datatype_ -> dataPlain+ Newtype_ -> dataPlain+ DataInstance_ con -> dataFamily con+ NewtypeInstance_ con -> dataFamily con++showNameQual :: Name -> String+showNameQual = sanitizeName . showQual+ where+ showQual (Name _ (NameQ m)) = modString m+ showQual (Name _ (NameG _ pkg m)) = pkgString pkg ++ ":" ++ modString m+ showQual _ = ""++-- | Credit to Víctor López Juan for this trick+sanitizeName :: String -> String+sanitizeName nb = 'N':(+ nb >>= \x -> case x of+ c | isAlphaNum c || c == '\''-> [c]+ '_' -> "__"+ c -> "_" ++ show (ord c))++-- | One of the last type variables cannot be eta-reduced (see the canEtaReduce+-- function for the criteria it would have to meet).+etaReductionError :: Type -> Q a+etaReductionError instanceType = fail $+ "Cannot eta-reduce to an instance of form \n\tinstance (...) => "+ ++ pprint instanceType++-- | Either the given data type doesn't have enough type variables, or one of+-- the type variables to be eta-reduced cannot realize kind *.+derivingKindError :: Name -> Q a+derivingKindError tyConName = fail+ . showString "Cannot derive well-kinded instance of form ‘Generic1 "+ . showParen True+ ( showString (nameBase tyConName)+ . showString " ..."+ )+ . showString "‘\n\tClass Generic1 expects an argument of kind "+#if MIN_VERSION_base(4,10,0)+ . showString "k -> *"+#else+ . showString "* -> *"+#endif+ $ ""++-- | The data type mentions the last type variable in a place other+-- than the last position of a data type in a constructor's field.+outOfPlaceTyVarError :: Q a+outOfPlaceTyVarError = fail+ . showString "Constructor must only use its last type variable as"+ . showString " the last argument of a data type"+ $ ""++-- | The data type mentions the last type variable in a type family+-- application.+typeFamilyApplicationError :: Q a+typeFamilyApplicationError = fail+ . showString "Constructor must not apply its last type variable"+ . showString " to an unsaturated type family"+ $ ""++-- | We cannot define implementations for @from(1)@ or @to(1)@ at the term level+-- for @type data@ declarations, which only exist at the type level.+typeDataError :: Name -> Q a+typeDataError dataName = fail+ . showString "Cannot derive instance for ‘"+ . showString (nameBase dataName)+ . showString "‘, which is a ‘type data‘ declaration"+ $ ""++-- | Cannot have a constructor argument of form (forall a1 ... an. <type>)+-- when deriving Generic(1)+rankNError :: Q a+rankNError = fail "Cannot have polymorphic arguments"++-- | Boilerplate for top level splices.+--+-- The given Name must meet one of two criteria:+--+-- 1. It must be the name of a type constructor of a plain data type or newtype.+-- 2. It must be the name of a data family instance or newtype instance constructor.+--+-- Any other value will result in an exception.+reifyDataInfo :: Name+ -> Q (Either String (Name, [Type], [ConstructorInfo], DatatypeVariant_))+reifyDataInfo name = do+ return $ Left $ ns ++ " Could not reify " ++ nameBase name+ `recover`+ do DatatypeInfo { datatypeContext = ctxt+ , datatypeName = parentName+ , datatypeInstTypes = tys+ , datatypeVariant = variant+ , datatypeCons = cons+ } <- reifyDatatype name+ variant_ <-+ case variant of+ Datatype -> return Datatype_+ Newtype -> return Newtype_+ DataInstance -> return $ DataInstance_ $ headDataFamInstCon parentName cons+ NewtypeInstance -> return $ NewtypeInstance_ $ headDataFamInstCon parentName cons+#if MIN_VERSION_th_abstraction(0,5,0)+ Datatype.TypeData -> typeDataError parentName+#endif+ checkDataContext parentName ctxt $ Right (parentName, tys, cons, variant_)+ where+ ns :: String+ ns = "Generics.Deriving.TH.reifyDataInfo: "++ -- This isn't total, but the API requires that the data family instance have+ -- at least one constructor anyways, so this will always succeed.+ headDataFamInstCon :: Name -> [ConstructorInfo] -> ConstructorInfo+ headDataFamInstCon dataFamName cons =+ case cons of+ con:_ -> con+ [] -> error $ "reified data family instance without a data constructor: "+ ++ nameBase dataFamName++-- | One cannot derive Generic(1) instance for anything that uses DatatypeContexts,+-- so check to make sure the Cxt field of a datatype is null.+checkDataContext :: Name -> Cxt -> a -> Q a+checkDataContext _ [] x = return x+checkDataContext dataName _ _ = fail $+ nameBase dataName ++ " must not have a datatype context"++-- | Deriving Generic(1) doesn't work with ExistentialQuantification or GADTs.+checkExistentialContext :: Name -> [TyVarBndrUnit] -> Cxt -> Q ()+checkExistentialContext constrName vars ctxt =+ unless (null vars && null ctxt) $ fail $+ nameBase constrName ++ " must be a vanilla data constructor"++#if !(MIN_VERSION_template_haskell(2,21,0)) && !(MIN_VERSION_th_abstraction(0,6,0))+type TyVarBndrVis = TyVarBndrUnit++bndrReq :: ()+bndrReq = ()+#endif++-------------------------------------------------------------------------------+-- Quoted names+-------------------------------------------------------------------------------++comp1DataName :: Name+comp1DataName = 'Comp1++infixDataName :: Name+infixDataName = 'GD.Infix++k1DataName :: Name+k1DataName = 'K1++l1DataName :: Name+l1DataName = 'L1++leftAssociativeDataName :: Name+leftAssociativeDataName = 'LeftAssociative++m1DataName :: Name+m1DataName = 'M1++notAssociativeDataName :: Name+notAssociativeDataName = 'NotAssociative++par1DataName :: Name+par1DataName = 'Par1++prefixDataName :: Name+prefixDataName = 'Prefix++productDataName :: Name+productDataName = '(:*:)++r1DataName :: Name+r1DataName = 'R1++rec1DataName :: Name+rec1DataName = 'Rec1++rightAssociativeDataName :: Name+rightAssociativeDataName = 'RightAssociative++u1DataName :: Name+u1DataName = 'U1++uAddrDataName :: Name+uAddrDataName = 'UAddr++uCharDataName :: Name+uCharDataName = 'UChar++uDoubleDataName :: Name+uDoubleDataName = 'UDouble++uFloatDataName :: Name+uFloatDataName = 'UFloat++uIntDataName :: Name+uIntDataName = 'UInt++uWordDataName :: Name+uWordDataName = 'UWord++c1TypeName :: Name+c1TypeName = ''C1++composeTypeName :: Name+composeTypeName = ''(:.:)++constructorTypeName :: Name+constructorTypeName = ''Constructor++d1TypeName :: Name+d1TypeName = ''D1++genericTypeName :: Name+genericTypeName = ''Generic++generic1TypeName :: Name+generic1TypeName = ''Generic1++datatypeTypeName :: Name+datatypeTypeName = ''Datatype++par1TypeName :: Name+par1TypeName = ''Par1++productTypeName :: Name+productTypeName = ''(:*:)++rec0TypeName :: Name+rec0TypeName = ''Rec0++rec1TypeName :: Name+rec1TypeName = ''Rec1++repTypeName :: Name+repTypeName = ''Rep++rep1TypeName :: Name+rep1TypeName = ''Rep1++s1TypeName :: Name+s1TypeName = ''S1++selectorTypeName :: Name+selectorTypeName = ''Selector++sumTypeName :: Name+sumTypeName = ''(:+:)++u1TypeName :: Name+u1TypeName = ''U1++uAddrTypeName :: Name+uAddrTypeName = ''UAddr++uCharTypeName :: Name+uCharTypeName = ''UChar++uDoubleTypeName :: Name+uDoubleTypeName = ''UDouble++uFloatTypeName :: Name+uFloatTypeName = ''UFloat++uIntTypeName :: Name+uIntTypeName = ''UInt++uWordTypeName :: Name+uWordTypeName = ''UWord++v1TypeName :: Name+v1TypeName = ''V1++conFixityValName :: Name+conFixityValName = 'conFixity++conIsRecordValName :: Name+conIsRecordValName = 'conIsRecord++conNameValName :: Name+conNameValName = 'GD.conName++datatypeNameValName :: Name+datatypeNameValName = 'GD.datatypeName++isNewtypeValName :: Name+isNewtypeValName = 'isNewtype++fromValName :: Name+fromValName = 'from++from1ValName :: Name+from1ValName = 'from1++moduleNameValName :: Name+moduleNameValName = 'moduleName++selNameValName :: Name+selNameValName = 'selName++seqValName :: Name+seqValName = 'seq++toValName :: Name+toValName = 'to++to1ValName :: Name+to1ValName = 'to1++uAddrHashValName :: Name+uAddrHashValName = 'uAddr#++uCharHashValName :: Name+uCharHashValName = 'uChar#++uDoubleHashValName :: Name+uDoubleHashValName = 'uDouble#++uFloatHashValName :: Name+uFloatHashValName = 'uFloat#++uIntHashValName :: Name+uIntHashValName = 'uInt#++uWordHashValName :: Name+uWordHashValName = 'uWord#++unComp1ValName :: Name+unComp1ValName = 'unComp1++unK1ValName :: Name+unK1ValName = 'unK1++unPar1ValName :: Name+unPar1ValName = 'unPar1++unRec1ValName :: Name+unRec1ValName = 'unRec1++trueDataName, falseDataName :: Name+trueDataName = 'True+falseDataName = 'False++nothingDataName, justDataName :: Name+nothingDataName = 'Nothing+justDataName = 'Just++addrHashTypeName :: Name+addrHashTypeName = ''Addr#++charHashTypeName :: Name+charHashTypeName = ''Char#++doubleHashTypeName :: Name+doubleHashTypeName = ''Double#++floatHashTypeName :: Name+floatHashTypeName = ''Float#++intHashTypeName :: Name+intHashTypeName = ''Int#++wordHashTypeName :: Name+wordHashTypeName = ''Word#++composeValName :: Name+composeValName = '(.)++errorValName :: Name+errorValName = 'error++fmapValName :: Name+fmapValName = 'fmap++undefinedValName :: Name+undefinedValName = 'undefined++decidedLazyDataName :: Name+decidedLazyDataName = 'GD.DecidedLazy++decidedStrictDataName :: Name+decidedStrictDataName = 'GD.DecidedStrict++decidedUnpackDataName :: Name+decidedUnpackDataName = 'GD.DecidedUnpack++infixIDataName :: Name+infixIDataName = 'InfixI++metaConsDataName :: Name+metaConsDataName = 'MetaCons++metaDataDataName :: Name+metaDataDataName = 'MetaData++metaSelDataName :: Name+metaSelDataName = 'MetaSel++noSourceStrictnessDataName :: Name+noSourceStrictnessDataName = 'GD.NoSourceStrictness++noSourceUnpackednessDataName :: Name+noSourceUnpackednessDataName = 'GD.NoSourceUnpackedness++prefixIDataName :: Name+prefixIDataName = 'PrefixI++sourceLazyDataName :: Name+sourceLazyDataName = 'GD.SourceLazy++sourceNoUnpackDataName :: Name+sourceNoUnpackDataName = 'GD.SourceNoUnpack++sourceStrictDataName :: Name+sourceStrictDataName = 'GD.SourceStrict++sourceUnpackDataName :: Name+sourceUnpackDataName = 'GD.SourceUnpack++packageNameValName :: Name+packageNameValName = 'packageName
+ src/Generics/Deriving/TH/Post4_9.hs view
@@ -0,0 +1,137 @@+{- |+Module : Generics.Deriving.TH.Post4_9+Copyright : (c) 2008--2009 Universiteit Utrecht+License : BSD3++Maintainer : generics@haskell.org+Stability : experimental+Portability : non-portable++Template Haskell machinery for the type-literal-based variant of GHC+generics introduced in @base-4.9@.+-}++module Generics.Deriving.TH.Post4_9 (+ deriveMeta+ , deriveData+ , deriveConstructors+ , deriveSelectors+ , mkMetaDataType+ , mkMetaConsType+ , mkMetaSelType+ , SelStrictInfo(..)+ , reifySelStrictInfo+ ) where++import Data.Maybe (fromMaybe)++import Generics.Deriving.TH.Internal++import Language.Haskell.TH.Datatype as THAbs+import Language.Haskell.TH.Lib+import Language.Haskell.TH.Syntax++mkMetaDataType :: DatatypeVariant_ -> Name -> Q Type+mkMetaDataType dv n =+ promotedT metaDataDataName+ `appT` litT (strTyLit (nameBase n))+ `appT` litT (strTyLit m)+ `appT` litT (strTyLit pkg)+ `appT` promoteBool (isNewtypeVariant dv)+ where+ m, pkg :: String+ m = fromMaybe (error "Cannot fetch module name!") (nameModule n)+ pkg = fromMaybe (error "Cannot fetch package name!") (namePackage n)++mkMetaConsType :: DatatypeVariant_ -> Name -> Name -> Bool -> Bool -> Q Type+mkMetaConsType _ _ n conIsRecord conIsInfix = do+ mbFi <- reifyFixity n+ promotedT metaConsDataName+ `appT` litT (strTyLit (nameBase n))+ `appT` fixityIPromotedType mbFi conIsInfix+ `appT` promoteBool conIsRecord++promoteBool :: Bool -> Q Type+promoteBool True = promotedT trueDataName+promoteBool False = promotedT falseDataName++fixityIPromotedType :: Maybe Fixity -> Bool -> Q Type+fixityIPromotedType mbFi True =+ promotedT infixIDataName+ `appT` promoteAssociativity a+ `appT` litT (numTyLit (toInteger n))+ where+ Fixity n a = fromMaybe defaultFixity mbFi+fixityIPromotedType _ False = promotedT prefixIDataName++promoteAssociativity :: FixityDirection -> Q Type+promoteAssociativity InfixL = promotedT leftAssociativeDataName+promoteAssociativity InfixR = promotedT rightAssociativeDataName+promoteAssociativity InfixN = promotedT notAssociativeDataName++mkMetaSelType :: DatatypeVariant_ -> Name -> Name -> Maybe Name+ -> SelStrictInfo -> Q Type+mkMetaSelType _ _ _ mbF (SelStrictInfo su ss ds) =+ let mbSelNameT = case mbF of+ Just f -> promotedT justDataName `appT` litT (strTyLit (nameBase f))+ Nothing -> promotedT nothingDataName+ in promotedT metaSelDataName+ `appT` mbSelNameT+ `appT` promoteUnpackedness su+ `appT` promoteStrictness ss+ `appT` promoteDecidedStrictness ds++data SelStrictInfo = SelStrictInfo Unpackedness Strictness DecidedStrictness++promoteUnpackedness :: Unpackedness -> Q Type+promoteUnpackedness UnspecifiedUnpackedness = promotedT noSourceUnpackednessDataName+promoteUnpackedness NoUnpack = promotedT sourceNoUnpackDataName+promoteUnpackedness Unpack = promotedT sourceUnpackDataName++promoteStrictness :: Strictness -> Q Type+promoteStrictness UnspecifiedStrictness = promotedT noSourceStrictnessDataName+promoteStrictness Lazy = promotedT sourceLazyDataName+promoteStrictness THAbs.Strict = promotedT sourceStrictDataName++promoteDecidedStrictness :: DecidedStrictness -> Q Type+promoteDecidedStrictness DecidedLazy = promotedT decidedLazyDataName+promoteDecidedStrictness DecidedStrict = promotedT decidedStrictDataName+promoteDecidedStrictness DecidedUnpack = promotedT decidedUnpackDataName++reifySelStrictInfo :: Name -> [FieldStrictness] -> Q [SelStrictInfo]+reifySelStrictInfo conName fs = do+ dcdStrs <- reifyConStrictness conName+ let srcUnpks = map fieldUnpackedness fs+ srcStrs = map fieldStrictness fs+ return $ zipWith3 SelStrictInfo srcUnpks srcStrs dcdStrs++-- | Given the type and the name (as string) for the type to derive,+-- generate the 'Data' instance, the 'Constructor' instances, and the 'Selector'+-- instances.+--+-- On GHC 7.11 and up, this functionality is no longer used in GHC generics,+-- so this function generates no declarations.+deriveMeta :: Name -> Q [Dec]+deriveMeta _ = return []++-- | Given a datatype name, derive a datatype and instance of class 'Datatype'.+--+-- On GHC 7.11 and up, this functionality is no longer used in GHC generics,+-- so this function generates no declarations.+deriveData :: Name -> Q [Dec]+deriveData _ = return []++-- | Given a datatype name, derive datatypes and+-- instances of class 'Constructor'.+--+-- On GHC 7.11 and up, this functionality is no longer used in GHC generics,+-- so this function generates no declarations.+deriveConstructors :: Name -> Q [Dec]+deriveConstructors _ = return []++-- | Given a datatype name, derive datatypes and instances of class 'Selector'.+--+-- On GHC 7.11 and up, this functionality is no longer used in GHC generics,+-- so this function generates no declarations.+deriveSelectors :: Name -> Q [Dec]+deriveSelectors _ = return []
src/Generics/Deriving/Traversable.hs view
@@ -1,82 +1,184 @@-{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - -module Generics.Deriving.Traversable ( - -- * GTraversable class - GTraversable(..) - - -- * Default method - , gtraversedefault - - ) where - -import Control.Applicative -import Generics.Deriving.Base -import Generics.Deriving.Foldable -import Generics.Deriving.Functor -import Generics.Deriving.Instances () - --------------------------------------------------------------------------------- --- Generic traverse --------------------------------------------------------------------------------- - -class GTraversable' t where - gtraverse' :: Applicative f => (a -> f b) -> t a -> f (t b) - -instance GTraversable' U1 where - gtraverse' _ U1 = pure U1 - -instance GTraversable' Par1 where - gtraverse' f (Par1 a) = Par1 <$> f a - -instance GTraversable' (K1 i c) where - gtraverse' _ (K1 a) = pure (K1 a) - -instance (GTraversable f) => GTraversable' (Rec1 f) where - gtraverse' f (Rec1 a) = Rec1 <$> gtraverse f a - -instance (GTraversable' f) => GTraversable' (M1 i c f) where - gtraverse' f (M1 a) = M1 <$> gtraverse' f a - -instance (GTraversable' f, GTraversable' g) => GTraversable' (f :+: g) where - gtraverse' f (L1 a) = L1 <$> gtraverse' f a - gtraverse' f (R1 a) = R1 <$> gtraverse' f a - -instance (GTraversable' f, GTraversable' g) => GTraversable' (f :*: g) where - gtraverse' f (a :*: b) = (:*:) <$> gtraverse' f a <*> gtraverse' f b - -instance (GTraversable f, GTraversable' g) => GTraversable' (f :.: g) where - gtraverse' f (Comp1 x) = Comp1 <$> gtraverse (gtraverse' f) x - - -class (GFunctor t, GFoldable t) => GTraversable t where - gtraverse :: Applicative f => (a -> f b) -> t a -> f (t b) -#if __GLASGOW_HASKELL__ >= 701 - default gtraverse :: (Generic1 t, GTraversable' (Rep1 t), Applicative f) - => (a -> f b) -> t a -> f (t b) - gtraverse = gtraversedefault -#endif - - gsequenceA :: Applicative f => t (f a) -> f (t a) - gsequenceA = gtraverse id - - gmapM :: Monad m => (a -> m b) -> t a -> m (t b) - gmapM f = unwrapMonad . gtraverse (WrapMonad . f) - - gsequence :: Monad m => t (m a) -> m (t a) - gsequence = gmapM id - -gtraversedefault :: (Generic1 t, GTraversable' (Rep1 t), Applicative f) - => (a -> f b) -> t a -> f (t b) -gtraversedefault f x = to1 <$> gtraverse' f (from1 x) - --- Base types instances -instance GTraversable Maybe where - gtraverse = gtraversedefault - -instance GTraversable [] where - gtraverse = gtraversedefault +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++module Generics.Deriving.Traversable (+ -- * Generic Traversable class+ GTraversable(..)++ -- * Default method+ , gtraversedefault++ -- * Internal Traversable class+ , GTraversable'(..)++ ) where++import Control.Applicative (Const, WrappedMonad(..), ZipList)++import Data.Complex (Complex)+import Data.Functor.Identity (Identity)+import qualified Data.Functor.Product as Functor (Product)+import qualified Data.Functor.Sum as Functor (Sum)+import Data.List.NonEmpty (NonEmpty)+import qualified Data.Monoid as Monoid (First, Last, Product, Sum)+import Data.Monoid (Dual)+import Data.Ord (Down)+import Data.Proxy (Proxy)+import qualified Data.Semigroup as Semigroup (First, Last)+import Data.Semigroup (Arg, Max, Min, WrappedMonoid)++import Generics.Deriving.Base+import Generics.Deriving.Foldable+import Generics.Deriving.Functor++--------------------------------------------------------------------------------+-- Generic traverse+--------------------------------------------------------------------------------++class GTraversable' t where+ gtraverse' :: Applicative f => (a -> f b) -> t a -> f (t b)++instance GTraversable' V1 where+ gtraverse' _ x = pure $ case x of {}++instance GTraversable' U1 where+ gtraverse' _ U1 = pure U1++instance GTraversable' Par1 where+ gtraverse' f (Par1 a) = Par1 <$> f a++instance GTraversable' (K1 i c) where+ gtraverse' _ (K1 a) = pure (K1 a)++instance (GTraversable f) => GTraversable' (Rec1 f) where+ gtraverse' f (Rec1 a) = Rec1 <$> gtraverse f a++instance (GTraversable' f) => GTraversable' (M1 i c f) where+ gtraverse' f (M1 a) = M1 <$> gtraverse' f a++instance (GTraversable' f, GTraversable' g) => GTraversable' (f :+: g) where+ gtraverse' f (L1 a) = L1 <$> gtraverse' f a+ gtraverse' f (R1 a) = R1 <$> gtraverse' f a++instance (GTraversable' f, GTraversable' g) => GTraversable' (f :*: g) where+ gtraverse' f (a :*: b) = (:*:) <$> gtraverse' f a <*> gtraverse' f b++instance (GTraversable f, GTraversable' g) => GTraversable' (f :.: g) where+ gtraverse' f (Comp1 x) = Comp1 <$> gtraverse (gtraverse' f) x++instance GTraversable' UAddr where+ gtraverse' _ (UAddr a) = pure (UAddr a)++instance GTraversable' UChar where+ gtraverse' _ (UChar c) = pure (UChar c)++instance GTraversable' UDouble where+ gtraverse' _ (UDouble d) = pure (UDouble d)++instance GTraversable' UFloat where+ gtraverse' _ (UFloat f) = pure (UFloat f)++instance GTraversable' UInt where+ gtraverse' _ (UInt i) = pure (UInt i)++instance GTraversable' UWord where+ gtraverse' _ (UWord w) = pure (UWord w)++class (GFunctor t, GFoldable t) => GTraversable t where+ gtraverse :: Applicative f => (a -> f b) -> t a -> f (t b)+ default gtraverse :: (Generic1 t, GTraversable' (Rep1 t), Applicative f)+ => (a -> f b) -> t a -> f (t b)+ gtraverse = gtraversedefault++ gsequenceA :: Applicative f => t (f a) -> f (t a)+ gsequenceA = gtraverse id++ gmapM :: Monad m => (a -> m b) -> t a -> m (t b)+ gmapM f = unwrapMonad . gtraverse (WrapMonad . f)++ gsequence :: Monad m => t (m a) -> m (t a)+ gsequence = gmapM id++gtraversedefault :: (Generic1 t, GTraversable' (Rep1 t), Applicative f)+ => (a -> f b) -> t a -> f (t b)+gtraversedefault f x = to1 <$> gtraverse' f (from1 x)++-- Base types instances+instance GTraversable ((,) a) where+ gtraverse = gtraversedefault++instance GTraversable [] where+ gtraverse = gtraversedefault++instance GTraversable (Arg a) where+ gtraverse = gtraversedefault++instance GTraversable Complex where+ gtraverse = gtraversedefault++instance GTraversable (Const m) where+ gtraverse = gtraversedefault++instance GTraversable Down where+ gtraverse = gtraversedefault++instance GTraversable Dual where+ gtraverse = gtraversedefault++instance GTraversable (Either a) where+ gtraverse = gtraversedefault++instance GTraversable Monoid.First where+ gtraverse = gtraversedefault++instance GTraversable (Semigroup.First) where+ gtraverse = gtraversedefault++instance GTraversable Identity where+ gtraverse = gtraversedefault++instance GTraversable Monoid.Last where+ gtraverse = gtraversedefault++instance GTraversable Semigroup.Last where+ gtraverse = gtraversedefault++instance GTraversable Max where+ gtraverse = gtraversedefault++instance GTraversable Maybe where+ gtraverse = gtraversedefault++instance GTraversable Min where+ gtraverse = gtraversedefault++instance GTraversable NonEmpty where+ gtraverse = gtraversedefault++instance GTraversable Monoid.Product where+ gtraverse = gtraversedefault++instance (GTraversable f, GTraversable g) => GTraversable (Functor.Product f g) where+ gtraverse = gtraversedefault++instance GTraversable Proxy where+ gtraverse = gtraversedefault++instance GTraversable Monoid.Sum where+ gtraverse = gtraversedefault++instance (GTraversable f, GTraversable g) => GTraversable (Functor.Sum f g) where+ gtraverse = gtraversedefault++instance GTraversable WrappedMonoid where+ gtraverse = gtraversedefault++instance GTraversable ZipList where+ gtraverse = gtraversedefault
src/Generics/Deriving/Uniplate.hs view
@@ -1,355 +1,345 @@-{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE OverlappingInstances #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE CPP #-} -#if __GLASGOW_HASKELL__ >= 701 -{-# LANGUAGE DefaultSignatures #-} -#endif - --------------------------------------------------------------------------------- --- | --- Module : Generics.Deriving.Uniplate --- Copyright : 2011-2012 Universiteit Utrecht, University of Oxford --- License : BSD3 --- --- Maintainer : generics@haskell.org --- Stability : experimental --- Portability : non-portable --- --- Summary: Functions inspired by the Uniplate generic programming library, --- mostly implemented by Sean Leather. --------------------------------------------------------------------------------- - -module Generics.Deriving.Uniplate ( - Uniplate(..) - - -- * Derived functions - , uniplate - , universe - , rewrite - , rewriteM - , contexts - , holes - , para - - -- * Default definitions - , childrendefault - , contextdefault - , descenddefault - , descendMdefault - , transformdefault - , transformMdefault - - ) where - - -import Generics.Deriving.Base -import Generics.Deriving.Instances () - -import Control.Monad (liftM, liftM2) -import GHC.Exts (build) - --------------------------------------------------------------------------------- --- Generic Uniplate --------------------------------------------------------------------------------- - -class Uniplate' f b where - children' :: f a -> [b] - descend' :: (b -> b) -> f a -> f a - descendM' :: Monad m => (b -> m b) -> f a -> m (f a) - transform' :: (b -> b) -> f a -> f a - transformM' :: Monad m => (b -> m b) -> f a -> m (f a) - -instance Uniplate' U1 a where - children' U1 = [] - descend' _ U1 = U1 - descendM' _ U1 = return U1 - transform' _ U1 = U1 - transformM' _ U1 = return U1 - -instance (Uniplate a) => Uniplate' (K1 i a) a where - children' (K1 a) = [a] - descend' f (K1 a) = K1 (f a) - descendM' f (K1 a) = liftM K1 (f a) - transform' f (K1 a) = K1 (transform f a) - transformM' f (K1 a) = liftM K1 (transformM f a) - -instance Uniplate' (K1 i a) b where - children' (K1 _) = [] - descend' _ (K1 a) = K1 a - descendM' _ (K1 a) = return (K1 a) - transform' _ (K1 a) = K1 a - transformM' _ (K1 a) = return (K1 a) - -instance (Uniplate' f b) => Uniplate' (M1 i c f) b where - children' (M1 a) = children' a - descend' f (M1 a) = M1 (descend' f a) - descendM' f (M1 a) = liftM M1 (descendM' f a) - transform' f (M1 a) = M1 (transform' f a) - transformM' f (M1 a) = liftM M1 (transformM' f a) - -instance (Uniplate' f b, Uniplate' g b) => Uniplate' (f :+: g) b where - children' (L1 a) = children' a - children' (R1 a) = children' a - descend' f (L1 a) = L1 (descend' f a) - descend' f (R1 a) = R1 (descend' f a) - descendM' f (L1 a) = liftM L1 (descendM' f a) - descendM' f (R1 a) = liftM R1 (descendM' f a) - transform' f (L1 a) = L1 (transform' f a) - transform' f (R1 a) = R1 (transform' f a) - transformM' f (L1 a) = liftM L1 (transformM' f a) - transformM' f (R1 a) = liftM R1 (transformM' f a) - -instance (Uniplate' f b, Uniplate' g b) => Uniplate' (f :*: g) b where - children' (a :*: b) = children' a ++ children' b - descend' f (a :*: b) = descend' f a :*: descend' f b - descendM' f (a :*: b) = liftM2 (:*:) (descendM' f a) (descendM' f b) - transform' f (a :*: b) = transform' f a :*: transform' f b - transformM' f (a :*: b) = liftM2 (:*:) (transformM' f a) (transformM' f b) - - --- Context' is a separate class from Uniplate' since it uses special product --- instances, but the context function still appears in Uniplate. -class Context' f b where - context' :: f a -> [b] -> f a - -instance Context' U1 b where - context' U1 _ = U1 - -instance Context' (K1 i a) a where - context' _ [] = error "Generics.Deriving.Uniplate.context: empty list" - context' (K1 _) (c:_) = K1 c - -instance Context' (K1 i a) b where - context' (K1 a) _ = K1 a - -instance (Context' f b) => Context' (M1 i c f) b where - context' (M1 a) cs = M1 (context' a cs) - -instance (Context' f b, Context' g b) => Context' (f :+: g) b where - context' (L1 a) cs = L1 (context' a cs) - context' (R1 a) cs = R1 (context' a cs) - -instance (Context' g a) => Context' (M1 i c (K1 j a) :*: g) a where - context' _ [] = error "Generics.Deriving.Uniplate.context: empty list" - context' (M1 (K1 _) :*: b) (c:cs) = M1 (K1 c) :*: context' b cs - -instance (Context' g b) => Context' (f :*: g) b where - context' (a :*: b) cs = a :*: context' b cs - - -class Uniplate a where - children :: a -> [a] -#if __GLASGOW_HASKELL__ >= 701 - default children :: (Generic a, Uniplate' (Rep a) a) => a -> [a] - children = childrendefault -#endif - - context :: a -> [a] -> a -#if __GLASGOW_HASKELL__ >= 701 - default context :: (Generic a, Context' (Rep a) a) => a -> [a] -> a - context = contextdefault -#endif - - descend :: (a -> a) -> a -> a -#if __GLASGOW_HASKELL__ >= 701 - default descend :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a - descend = descenddefault -#endif - - descendM :: Monad m => (a -> m a) -> a -> m a -#if __GLASGOW_HASKELL__ >= 701 - default descendM :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a - descendM = descendMdefault -#endif - - transform :: (a -> a) -> a -> a -#if __GLASGOW_HASKELL__ >= 701 - default transform :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a - transform = transformdefault -#endif - - transformM :: Monad m => (a -> m a) -> a -> m a -#if __GLASGOW_HASKELL__ >= 701 - default transformM :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a - transformM = transformMdefault -#endif - -childrendefault :: (Generic a, Uniplate' (Rep a) a) => a -> [a] -childrendefault = children' . from - -contextdefault :: (Generic a, Context' (Rep a) a) => a -> [a] -> a -contextdefault x cs = to (context' (from x) cs) - -descenddefault :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a -descenddefault f = to . descend' f . from - -descendMdefault :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a -descendMdefault f = liftM to . descendM' f . from - -transformdefault :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a -transformdefault f = f . to . transform' f . from - -transformMdefault :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a -transformMdefault f = liftM to . transformM' f . from - - --- Derived functions (mostly copied from Neil Michell's code) - -uniplate :: Uniplate a => a -> ([a], [a] -> a) -uniplate a = (children a, context a) - -universe :: Uniplate a => a -> [a] -universe a = build (go a) - where - go x cons nil = cons x $ foldr ($) nil $ map (\c -> go c cons) $ children x - -rewrite :: Uniplate a => (a -> Maybe a) -> a -> a -rewrite f = transform g - where - g x = maybe x (rewrite f) (f x) - -rewriteM :: (Monad m, Uniplate a) => (a -> m (Maybe a)) -> a -> m a -rewriteM f = transformM g - where - g x = f x >>= maybe (return x) (rewriteM f) - -contexts :: Uniplate a => a -> [(a, a -> a)] -contexts a = (a, id) : f (holes a) - where - f xs = [ (ch2, ctx1 . ctx2) - | (ch1, ctx1) <- xs - , (ch2, ctx2) <- contexts ch1] - -holes :: Uniplate a => a -> [(a, a -> a)] -holes a = uncurry f (uniplate a) - where - f [] _ = [] - f (x:xs) gen = (x, gen . (:xs)) : f xs (gen . (x:)) - -para :: Uniplate a => (a -> [r] -> r) -> a -> r -para f x = f x $ map (para f) $ children x - - --- Base types instances -instance Uniplate Bool where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate Char where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate Double where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate Float where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate Int where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate () where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return - --- Tuple instances -instance Uniplate (b,c) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (b,c,d) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (b,c,d,e) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (b,c,d,e,f) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (b,c,d,e,f,g) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (b,c,d,e,f,g,h) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return - --- Parameterized type instances -instance Uniplate (Maybe a) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return -instance Uniplate (Either a b) where - children _ = [] - context x _ = x - descend _ = id - descendM _ = return - transform = id - transformM _ = return - -instance Uniplate [a] where - children [] = [] - children (_:t) = [t] - context _ [] = error "Generics.Deriving.Uniplate.context: empty list" - context [] _ = [] - context (h:_) (t:_) = h:t - descend _ [] = [] - descend f (h:t) = h:f t - descendM _ [] = return [] - descendM f (h:t) = f t >>= \t' -> return (h:t') - transform f [] = f [] - transform f (h:t) = f (h:transform f t) - transformM f [] = f [] - transformM f (h:t) = transformM f t >>= \t' -> f (h:t') - +{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++{- |+Module : Generics.Deriving.Uniplate+Copyright : 2011-2012 Universiteit Utrecht, University of Oxford+License : BSD3++Maintainer : generics@haskell.org+Stability : experimental+Portability : non-portable++Summary: Functions inspired by the Uniplate generic programming library,+mostly implemented by Sean Leather.+-}++module Generics.Deriving.Uniplate (+ -- * Generic Uniplate class+ Uniplate(..)++ -- * Derived functions+ , uniplate+ , universe+ , rewrite+ , rewriteM+ , contexts+ , holes+ , para++ -- * Default definitions+ , childrendefault+ , contextdefault+ , descenddefault+ , descendMdefault+ , transformdefault+ , transformMdefault++ -- * Internal Uniplate class+ , Uniplate'(..)++ -- * Internal Context class+ , Context'(..)+ ) where+++import Generics.Deriving.Base++import Control.Monad (liftM, liftM2)+import GHC.Exts (build)++--------------------------------------------------------------------------------+-- Generic Uniplate+--------------------------------------------------------------------------------++class Uniplate' f b where+ children' :: f a -> [b]+ descend' :: (b -> b) -> f a -> f a+ descendM' :: Monad m => (b -> m b) -> f a -> m (f a)+ transform' :: (b -> b) -> f a -> f a+ transformM' :: Monad m => (b -> m b) -> f a -> m (f a)++instance Uniplate' U1 a where+ children' U1 = []+ descend' _ U1 = U1+ descendM' _ U1 = return U1+ transform' _ U1 = U1+ transformM' _ U1 = return U1++instance {-# OVERLAPPING #-} (Uniplate a) => Uniplate' (K1 i a) a where+ children' (K1 a) = [a]+ descend' f (K1 a) = K1 (f a)+ descendM' f (K1 a) = liftM K1 (f a)+ transform' f (K1 a) = K1 (transform f a)+ transformM' f (K1 a) = liftM K1 (transformM f a)++instance {-# OVERLAPPABLE #-} Uniplate' (K1 i a) b where+ children' (K1 _) = []+ descend' _ (K1 a) = K1 a+ descendM' _ (K1 a) = return (K1 a)+ transform' _ (K1 a) = K1 a+ transformM' _ (K1 a) = return (K1 a)++instance (Uniplate' f b) => Uniplate' (M1 i c f) b where+ children' (M1 a) = children' a+ descend' f (M1 a) = M1 (descend' f a)+ descendM' f (M1 a) = liftM M1 (descendM' f a)+ transform' f (M1 a) = M1 (transform' f a)+ transformM' f (M1 a) = liftM M1 (transformM' f a)++instance (Uniplate' f b, Uniplate' g b) => Uniplate' (f :+: g) b where+ children' (L1 a) = children' a+ children' (R1 a) = children' a+ descend' f (L1 a) = L1 (descend' f a)+ descend' f (R1 a) = R1 (descend' f a)+ descendM' f (L1 a) = liftM L1 (descendM' f a)+ descendM' f (R1 a) = liftM R1 (descendM' f a)+ transform' f (L1 a) = L1 (transform' f a)+ transform' f (R1 a) = R1 (transform' f a)+ transformM' f (L1 a) = liftM L1 (transformM' f a)+ transformM' f (R1 a) = liftM R1 (transformM' f a)++instance (Uniplate' f b, Uniplate' g b) => Uniplate' (f :*: g) b where+ children' (a :*: b) = children' a ++ children' b+ descend' f (a :*: b) = descend' f a :*: descend' f b+ descendM' f (a :*: b) = liftM2 (:*:) (descendM' f a) (descendM' f b)+ transform' f (a :*: b) = transform' f a :*: transform' f b+ transformM' f (a :*: b) = liftM2 (:*:) (transformM' f a) (transformM' f b)+++-- Context' is a separate class from Uniplate' since it uses special product+-- instances, but the context function still appears in Uniplate.+class Context' f b where+ context' :: f a -> [b] -> f a++instance Context' U1 b where+ context' U1 _ = U1++instance {-# OVERLAPPING #-} Context' (K1 i a) a where+ context' _ [] = error "Generics.Deriving.Uniplate.context: empty list"+ context' (K1 _) (c:_) = K1 c++instance {-# OVERLAPPABLE #-} Context' (K1 i a) b where+ context' (K1 a) _ = K1 a++instance (Context' f b) => Context' (M1 i c f) b where+ context' (M1 a) cs = M1 (context' a cs)++instance (Context' f b, Context' g b) => Context' (f :+: g) b where+ context' (L1 a) cs = L1 (context' a cs)+ context' (R1 a) cs = R1 (context' a cs)++instance {-# OVERLAPPING #-} (Context' g a) => Context' (M1 i c (K1 j a) :*: g) a where+ context' _ [] = error "Generics.Deriving.Uniplate.context: empty list"+ context' (M1 (K1 _) :*: b) (c:cs) = M1 (K1 c) :*: context' b cs++instance {-# OVERLAPPABLE #-} (Context' g b) => Context' (f :*: g) b where+ context' (a :*: b) cs = a :*: context' b cs+++class Uniplate a where+ children :: a -> [a]+ default children :: (Generic a, Uniplate' (Rep a) a) => a -> [a]+ children = childrendefault++ context :: a -> [a] -> a+ default context :: (Generic a, Context' (Rep a) a) => a -> [a] -> a+ context = contextdefault++ descend :: (a -> a) -> a -> a+ default descend :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a+ descend = descenddefault++ descendM :: Monad m => (a -> m a) -> a -> m a+ default descendM :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a+ descendM = descendMdefault++ transform :: (a -> a) -> a -> a+ default transform :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a+ transform = transformdefault++ transformM :: Monad m => (a -> m a) -> a -> m a+ default transformM :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a+ transformM = transformMdefault++childrendefault :: (Generic a, Uniplate' (Rep a) a) => a -> [a]+childrendefault = children' . from++contextdefault :: (Generic a, Context' (Rep a) a) => a -> [a] -> a+contextdefault x cs = to (context' (from x) cs)++descenddefault :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a+descenddefault f = to . descend' f . from++descendMdefault :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a+descendMdefault f = liftM to . descendM' f . from++transformdefault :: (Generic a, Uniplate' (Rep a) a) => (a -> a) -> a -> a+transformdefault f = f . to . transform' f . from++transformMdefault :: (Generic a, Uniplate' (Rep a) a, Monad m) => (a -> m a) -> a -> m a+transformMdefault f = liftM to . transformM' f . from+++-- Derived functions (mostly copied from Neil Michell's code)++uniplate :: Uniplate a => a -> ([a], [a] -> a)+uniplate a = (children a, context a)++universe :: Uniplate a => a -> [a]+universe a = build (go a)+ where+ go x cons nil = cons x $ foldr ($) nil $ map (\c -> go c cons) $ children x++rewrite :: Uniplate a => (a -> Maybe a) -> a -> a+rewrite f = transform g+ where+ g x = maybe x (rewrite f) (f x)++rewriteM :: (Monad m, Uniplate a) => (a -> m (Maybe a)) -> a -> m a+rewriteM f = transformM g+ where+ g x = f x >>= maybe (return x) (rewriteM f)++contexts :: Uniplate a => a -> [(a, a -> a)]+contexts a = (a, id) : f (holes a)+ where+ f xs = [ (ch2, ctx1 . ctx2)+ | (ch1, ctx1) <- xs+ , (ch2, ctx2) <- contexts ch1]++holes :: Uniplate a => a -> [(a, a -> a)]+holes a = uncurry f (uniplate a)+ where+ f [] _ = []+ f (x:xs) gen = (x, gen . (:xs)) : f xs (gen . (x:))++para :: Uniplate a => (a -> [r] -> r) -> a -> r+para f x = f x $ map (para f) $ children x+++-- Base types instances+instance Uniplate Bool where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate Char where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate Double where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate Float where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate Int where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate () where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return++-- Tuple instances+instance Uniplate (b,c) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (b,c,d) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (b,c,d,e) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (b,c,d,e,f) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (b,c,d,e,f,g) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (b,c,d,e,f,g,h) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return++-- Parameterized type instances+instance Uniplate (Maybe a) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return+instance Uniplate (Either a b) where+ children _ = []+ context x _ = x+ descend _ = id+ descendM _ = return+ transform = id+ transformM _ = return++instance Uniplate [a] where+ children [] = []+ children (_:t) = [t]+ context _ [] = error "Generics.Deriving.Uniplate.context: empty list"+ context [] _ = []+ context (h:_) (t:_) = h:t+ descend _ [] = []+ descend f (h:t) = h:f t+ descendM _ [] = return []+ descendM f (h:t) = f t >>= \t' -> return (h:t')+ transform f [] = f []+ transform f (h:t) = f (h:transform f t)+ transformM f [] = f []+ transformM f (h:t) = transformM f t >>= \t' -> f (h:t')+
+ tests/DefaultSpec.hs view
@@ -0,0 +1,161 @@+-- |+-- Module : DefaultSpec+-- Description : Ensure that deriving via (Default a) newtype works+-- License : BSD-3-Clause+--+-- Maintainer : generics@haskell.org+-- Stability : experimental+-- Portability : non-portable+--+-- Tests DerivingVia on GHC versions 8.6 and above. There are no tests on+-- versions below.+--+-- The test check a miscellany of properties of the derived type classes.+-- (Testing all the required properties is beyond the scope of this module.)+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 806+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+#endif++module DefaultSpec where++import Test.Hspec++#if __GLASGOW_HASKELL__ >= 806+import Test.Hspec.QuickCheck++import Data.Semigroup (First(..))+import Data.Foldable (sequenceA_)+import Generics.Deriving hiding (universe)+import Generics.Deriving.Default ()+import Generics.Deriving.Foldable (GFoldable(..))+import Generics.Deriving.Semigroup (GSemigroup(..))+#endif++spec :: Spec+spec = do+ describe "DerivingVia Default" $ do++#if __GLASGOW_HASKELL__ >= 806+ it "GEq is commutative for derivingVia (Default MyType)" . sequenceA_ $+ let commutative :: GEq a => a -> a -> Expectation+ commutative x y = x `geq` y `shouldBe` y `geq` x++ universe :: [MyType]+ universe = MyType <$> [False, True]++ in commutative <$> universe <*> universe++ it "GShow for MyType is like Show for Bool with derivingVia (Default MyType) but prefixed with 'MyType '" $ do+ gshowsPrec 0 (MyType False) "" `shouldBe` "MyType " <> showsPrec 0 False ""+ gshowsPrec 0 (MyType True) "" `shouldBe` "MyType " <> showsPrec 0 True ""++ it "GEq is commutative for parameterized derivingVia (Default (MyType1 Bool))" . sequenceA_ $+ let commutative :: GEq a => a -> a -> Expectation+ commutative x y = x `geq` y `shouldBe` y `geq` x++ universe :: [MyType1 Bool]+ universe = MyType1 <$> [False, True]++ in commutative <$> universe <*> universe++ it "GShow for MyType1 Bool is like Show for Bool with derivingVia (Default (MyType1 Bool)) but prefixed with 'MyType1 '" $ do+ gshowsPrec 0 (MyType1 False) "" `shouldBe` "MyType1 " <> showsPrec 0 False ""+ gshowsPrec 0 (MyType1 True) "" `shouldBe` "MyType1 " <> showsPrec 0 True ""++ it "GEq is commutative for derivingVia (Default Bool)" . sequenceA_ $+ let commutative :: GEq a => a -> a -> Expectation+ commutative x y = x `geq` y `shouldBe` y `geq` x++ universe :: [TestEq]+ universe = TestEq <$> [False, True]++ in commutative <$> universe <*> universe++ it "GENum is correct for derivingVia (Default Bool)" $+ genum `shouldBe` [TestEnum False, TestEnum True]++ it "GShow for TestShow is the same as Show for Bool with derivingVia (Default Bool)" $ do+ gshowsPrec 0 (TestShow False) "" `shouldBe` showsPrec 0 False ""+ gshowsPrec 0 (TestShow True) "" `shouldBe` showsPrec 0 True ""++ it "GSemigroup is like First when instantiated with derivingVia (First Bool)" . sequenceA_ $+ let first' :: (Eq a, Show a, GSemigroup a) => a -> a -> Expectation+ first' x y = x `gsappend` y `shouldBe` x++ universe :: [FirstSemigroup]+ universe = FirstSemigroup <$> [False, True]++ in first' <$> universe <*> universe++ prop "GFoldable with derivingVia (Default1 Option) acts like mconcat with Maybe (First Bool)" $ \(xs :: [Maybe Bool]) ->+ let ys :: [Maybe (First Bool)]+ -- Note that there is no Arbitrary instance for this type+ ys = fmap First <$> xs++ unTestFoldable :: TestFoldable a -> Maybe a+ unTestFoldable (TestFoldable x) = x++ in gfoldMap unTestFoldable (TestFoldable <$> ys) `shouldBe` mconcat ys++ it "GFunctor for TestFunctor Bool is as Functor for Maybe Bool" . sequenceA_ $+ let universe :: [Maybe Bool]+ universe = [Nothing, Just False, Just True]++ functor_prop :: Maybe Bool -> Expectation+ functor_prop x = gmap not (TestFunctor x) `shouldBe` TestFunctor (not <$> x)++ in functor_prop <$> universe++#endif+ return ()++#if __GLASGOW_HASKELL__ >= 806++-- These types all implement instances using `DerivingVia`: most via+-- `Default` (one uses `First`).++newtype TestEq = TestEq Bool+ deriving (GEq) via (Default Bool)+newtype TestEnum = TestEnum Bool+ deriving stock (Eq, Show)+ deriving (GEnum) via (Default Bool)+newtype TestShow = TestShow Bool+ deriving (GShow) via (Default Bool)++newtype FirstSemigroup = FirstSemigroup Bool+ deriving stock (Eq, Show)+ deriving (GSemigroup) via (First Bool)++newtype TestFoldable a = TestFoldable (Maybe a)+ deriving (GFoldable) via (Default1 Maybe)++newtype TestFunctor a = TestFunctor (Maybe a)+ deriving stock (Eq, Show, Functor)+ deriving (GFunctor) via (Default1 Maybe)++newtype TestHigherEq a = TestHigherEq (Maybe a)+ deriving stock (Generic)+ deriving (GEq) via (Default (TestHigherEq a))++-- These types correspond to the hypothetical examples in the module+-- documentation.++data MyType = MyType Bool+ deriving (Generic)+ deriving (GEq) via (Default MyType)++deriving via (Default MyType) instance GShow MyType++data MyType1 a = MyType1 a+ deriving (Generic, Generic1)+ deriving (GEq) via (Default (MyType1 a))+ deriving (GFunctor) via (Default1 MyType1)++deriving via Default (MyType1 a) instance GShow a => GShow (MyType1 a)+deriving via (Default1 MyType1) instance GFoldable MyType1+#endif
+ tests/EmptyCaseSpec.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++module EmptyCaseSpec (main, spec) where++import Generics.Deriving.TH+import Test.Hspec++data Empty a+$(deriveAll0And1Options defaultOptions{emptyCaseOptions = True}+ ''Empty)++main :: IO ()+main = hspec spec++spec :: Spec+spec = return ()
+ tests/ExampleSpec.hs view
@@ -0,0 +1,393 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module ExampleSpec (main, spec) where++import Generics.Deriving+import Generics.Deriving.TH++import GHC.Exts (Addr#, Char#, Double#, Float#, Int#, Word#)++import Prelude hiding (Either(..))++import Test.Hspec (Spec, describe, hspec, it, parallel, shouldBe)++import qualified Text.Read.Lex (Lexeme)++-------------------------------------------------------------------------------+-- Example: Haskell's lists and Maybe+-------------------------------------------------------------------------------++hList:: [Int]+hList = [1..10]++maybe1, maybe2 :: Maybe (Maybe Char)+maybe1 = Nothing+maybe2 = Just (Just 'p')++double :: [Int] -> [Int]+double [] = []+double (x:xs) = x:x:xs++-------------------------------------------------------------------------------+-- Example: trees of integers (kind *)+-------------------------------------------------------------------------------++data Tree = Empty | Branch Int Tree Tree++$(deriveAll0 ''Tree)++instance GShow Tree where+ gshowsPrec = gshowsPrecdefault++instance Uniplate Tree where+ children = childrendefault+ context = contextdefault+ descend = descenddefault+ descendM = descendMdefault+ transform = transformdefault+ transformM = transformMdefault++instance GEnum Tree where+ genum = genumDefault++upgradeTree :: Tree -> Tree+upgradeTree Empty = Branch 0 Empty Empty+upgradeTree (Branch n l r) = Branch (succ n) l r++tree :: Tree+tree = Branch 2 Empty (Branch 1 Empty Empty)++-------------------------------------------------------------------------------+-- Example: lists (kind * -> *)+-------------------------------------------------------------------------------++data List a = Nil | Cons a (List a)++$(deriveAll0And1 ''List)++instance GFunctor List where+ gmap = gmapdefault++instance (GShow a) => GShow (List a) where+ gshowsPrec = gshowsPrecdefault++instance (Uniplate a) => Uniplate (List a) where+ children = childrendefault+ context = contextdefault+ descend = descenddefault+ descendM = descendMdefault+ transform = transformdefault+ transformM = transformMdefault++list :: List Char+list = Cons 'p' (Cons 'q' Nil)++listlist :: List (List Char)+listlist = Cons list (Cons Nil Nil) -- ["pq",""]++-------------------------------------------------------------------------------+-- Example: Type composition+-------------------------------------------------------------------------------++data Rose a = Rose [a] [Rose a]++$(deriveAll0And1 ''Rose)++instance (GShow a) => GShow (Rose a) where+ gshowsPrec = gshowsPrecdefault++instance GFunctor Rose where+ gmap = gmapdefault++-- Example usage+rose1 :: Rose Int+rose1 = Rose [1,2] [Rose [3,4] [], Rose [5] []]++-------------------------------------------------------------------------------+-- Example: Higher-order kinded datatype, type composition+-------------------------------------------------------------------------------++data GRose f a = GRose (f a) (f (GRose f a))+deriving instance Functor f => Functor (GRose f)++$(deriveMeta ''GRose)+$(deriveRepresentable0 ''GRose)+$(deriveRep1 ''GRose)+instance Functor f => Generic1 (GRose f) where+ type Rep1 (GRose f) = $(makeRep1 ''GRose) f+ from1 = $(makeFrom1 ''GRose)+ to1 = $(makeTo1 ''GRose)++instance (GShow (f a), GShow (f (GRose f a))) => GShow (GRose f a) where+ gshowsPrec = gshowsPrecdefault++instance (Functor f, GFunctor f) => GFunctor (GRose f) where+ gmap = gmapdefault++grose1 :: GRose [] Int+grose1 = GRose [1,2] [GRose [3] [], GRose [] []]++-------------------------------------------------------------------------------+-- Example: Two parameters, nested on other parameter+-------------------------------------------------------------------------------++data Either a b = Left (Either [a] b) | Right b++$(deriveAll0And1 ''Either)++instance (GShow a, GShow b) => GShow (Either a b) where+ gshowsPrec = gshowsPrecdefault++instance GFunctor (Either a) where+ gmap = gmapdefault++either1 :: Either Int Char+either1 = Left either2++either2 :: Either [Int] Char+either2 = Right 'p'++-------------------------------------------------------------------------------+-- Example: Nested datatype, record selectors+-------------------------------------------------------------------------------++data Nested a = Leaf | Nested { value :: a, rec :: Nested [a] }+ deriving Functor++$(deriveAll0And1 ''Nested)++instance (GShow a) => GShow (Nested a) where+ gshowsPrec = gshowsPrecdefault++instance GFunctor Nested where+ gmap = gmapdefault++nested :: Nested Int+nested = Nested { value = 1, rec = Nested [2] (Nested [[3],[4,5],[]] Leaf) }++-------------------------------------------------------------------------------+-- Example: Nested datatype Bush (minimal)+-------------------------------------------------------------------------------++data Bush a = BushNil | BushCons a (Bush (Bush a)) deriving Functor++$(deriveAll0And1 ''Bush)++instance GFunctor Bush where+ gmap = gmapdefault++instance (GShow a) => GShow (Bush a) where+ gshowsPrec = gshowsPrecdefault++bush1 :: Bush Int+bush1 = BushCons 0 (BushCons (BushCons 1 BushNil) BushNil)++-------------------------------------------------------------------------------+-- Example: Double type composition (minimal)+-------------------------------------------------------------------------------++data Weird a = Weird [[[a]]] deriving Show++$(deriveAll0And1 ''Weird)++instance GFunctor Weird where+ gmap = gmapdefault++--------------------------------------------------------------------------------+-- Temporary tests for TH generation+--------------------------------------------------------------------------------++data Empty a++data (:/:) f a = MyType1Nil+ | MyType1Cons { _myType1Rec :: (f :/: a), _myType2Rec :: MyType2 }+ | MyType1Cons2 (f :/: a) Int a (f a)+ | (f :/: a) :/: MyType2++infixr 5 :!@!:+data GADTSyntax a b where+ GADTPrefix :: d -> c -> GADTSyntax c d+ (:!@!:) :: e -> f -> GADTSyntax e f++data MyType2 = MyType2 Float ([] :/: Int)+data PlainHash a = Hash a Addr# Char# Double# Float# Int# Word#++-- Test to see if generated names are unique+data Lexeme = Lexeme++data family MyType3 (a :: v) (b :: w) (c :: x) (d :: y) (e :: z)+newtype instance MyType3 (f p) (f p) f p (q :: *) = MyType3Newtype q+data instance MyType3 Bool () f p q = MyType3True | MyType3False+data instance MyType3 Int () f p (q :: *) = MyType3Hash q Addr# Char# Double# Float# Int# Word#++$(deriveAll0And1 ''Empty)+$(deriveAll0And1 ''(:/:))+$(deriveAll0And1 ''GADTSyntax)+$(deriveAll0 ''MyType2)+$(deriveAll0And1 ''PlainHash)+$(deriveAll0 ''ExampleSpec.Lexeme)+$(deriveAll0 ''Text.Read.Lex.Lexeme)++$(deriveAll0And1 'MyType3Newtype)+$(deriveAll0And1 'MyType3False)+$(deriveAll0And1 'MyType3Hash)++-------------------------------------------------------------------------------+-- Unit tests+-------------------------------------------------------------------------------++main :: IO ()+main = hspec spec++spec :: Spec+spec = parallel $ do+ describe "[] and Maybe tests" $ do+ it "gshow hList" $+ gshow hList `shouldBe`+ "[1,2,3,4,5,6,7,8,9,10]"++ it "gshow (children maybe2)" $+ gshow (children maybe2) `shouldBe`+ "[]"++ it "gshow (transform (const \"abc\") [])" $+ gshow (transform (const "abc") []) `shouldBe`+ "\"abc\""++ it "gshow (transform double hList)" $+ gshow (transform double hList) `shouldBe`+ "[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10]"++ it "gshow (geq hList hList)" $+ gshow (geq hList hList) `shouldBe`+ "True"++ it "gshow (geq maybe1 maybe2)" $+ gshow (geq maybe1 maybe2) `shouldBe`+ "False"++ it "gshow (take 5 genum)" $+ gshow (take 5 (genum :: [Maybe Int])) `shouldBe`+ "[Nothing,Just 0,Just -1,Just 1,Just -2]"++ it "gshow (take 15 genum)" $+ gshow (take 15 (genum :: [[Int]])) `shouldBe`+ "[[],[0],[0,0],[-1],[0,0,0],[-1,0],[1],[0,-1],[-1,0,0],[1,0],[-2],[0,0,0,0],[-1,-1],[1,0,0],[-2,0]]"++ it "gshow (range ([0], [1]))" $+ gshow (range ([0], [1::Int])) `shouldBe`+ "[[0],[0,0],[-1],[0,0,0],[-1,0]]"++ it "gshow (inRange ([0], [3,5]) hList)" $+ gshow (inRange ([0], [3,5::Int]) hList) `shouldBe`+ "False"++ describe "Tests for Tree" $ do+ it "gshow tree" $+ gshow tree `shouldBe`+ "Branch 2 Empty (Branch 1 Empty Empty)"++ it "gshow (children tree)" $+ gshow (children tree) `shouldBe`+ "[Empty,Branch 1 Empty Empty]"++ it "gshow (descend (descend (\\_ -> Branch 0 Empty Empty)) tree)" $+ gshow (descend (descend (\_ -> Branch 0 Empty Empty)) tree) `shouldBe`+ "Branch 2 Empty (Branch 1 (Branch 0 Empty Empty) (Branch 0 Empty Empty))"++ it "gshow (context tree [Branch 1 Empty Empty,Empty])" $+ gshow (context tree [Branch 1 Empty Empty,Empty]) `shouldBe`+ "Branch 2 (Branch 1 Empty Empty) Empty"++ it "gshow (transform upgradeTree tree)" $+ gshow (transform upgradeTree tree) `shouldBe`+ "Branch 3 (Branch 0 Empty Empty) (Branch 2 (Branch 0 Empty Empty) (Branch 0 Empty Empty))"++ it "gshow (take 10 genum)" $ do+ gshow (take 10 (genum :: [Tree])) `shouldBe`+ "[Empty,Branch 0 Empty Empty,Branch 0 Empty (Branch 0 Empty Empty),Branch -1 Empty Empty,Branch 0 (Branch 0 Empty Empty) Empty,Branch -1 Empty (Branch 0 Empty Empty),Branch 1 Empty Empty,Branch 0 Empty (Branch 0 Empty (Branch 0 Empty Empty)),Branch -1 (Branch 0 Empty Empty) Empty,Branch 1 Empty (Branch 0 Empty Empty)]"++ describe "Tests for List" $ do+ it "gshow (gmap fromEnum list)" $+ gshow (gmap fromEnum list) `shouldBe`+ "Cons 112 (Cons 113 Nil)"++ it "gshow (gmap gshow listlist)" $+ gshow (gmap gshow listlist) `shouldBe`+ "Cons \"Cons 'p' (Cons 'q' Nil)\" (Cons \"Nil\" Nil)"++ it "gshow list" $+ gshow list `shouldBe`+ "Cons 'p' (Cons 'q' Nil)"++ it "gshow listlist" $+ gshow listlist `shouldBe`+ "Cons (Cons 'p' (Cons 'q' Nil)) (Cons Nil Nil)"++ it "gshow (children list)" $+ gshow (children list) `shouldBe`+ "[Cons 'q' Nil]"++ it "gshow (children listlist)" $+ gshow (children listlist) `shouldBe`+ "[Cons Nil Nil]"++ describe "Tests for Rose" $ do+ it "gshow rose1" $+ gshow rose1 `shouldBe`+ "Rose [1,2] [Rose [3,4] [],Rose [5] []]"++ it "gshow (gmap gshow rose1)" $+ gshow (gmap gshow rose1) `shouldBe`+ "Rose [\"1\",\"2\"] [Rose [\"3\",\"4\"] [],Rose [\"5\"] []]"++ describe "Tests for GRose" $ do+ it "gshow grose1" $+ gshow grose1 `shouldBe`+ "GRose [1,2] [GRose [3] [],GRose [] []]"++ it "gshow (gmap gshow grose1)" $+ gshow (gmap gshow grose1) `shouldBe`+ "GRose [\"1\",\"2\"] [GRose [\"3\"] [],GRose [] []]"++ describe "Tests for Either" $ do+ it "gshow either1" $+ gshow either1 `shouldBe`+ "Left Right 'p'"++ it "gshow (gmap gshow either1)" $+ gshow (gmap gshow either1) `shouldBe`+ "Left Right \"'p'\""++ describe "Tests for Nested" $ do+ it "gshow nested" $+ gshow nested `shouldBe`+ "Nested {value = 1, rec = Nested {value = [2], rec = Nested {value = [[3],[4,5],[]], rec = Leaf}}}"++ it "gshow (gmap gshow nested)" $+ gshow (gmap gshow nested) `shouldBe`+ "Nested {value = \"1\", rec = Nested {value = [\"2\"], rec = Nested {value = [[\"3\"],[\"4\",\"5\"],[]], rec = Leaf}}}"++ describe "Tests for Bush" $ do+ it "gshow bush1" $+ gshow bush1 `shouldBe`+ "BushCons 0 (BushCons (BushCons 1 BushNil) BushNil)"++ it "gshow (gmap gshow bush1)" $+ gshow (gmap gshow bush1) `shouldBe`+ "BushCons \"0\" (BushCons (BushCons \"1\" BushNil) BushNil)"
+ tests/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ tests/T68Spec.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++module T68Spec (main, spec) where++import Generics.Deriving.TH+import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec = return ()++type family F68 :: * -> *+type instance F68 = Maybe+data T68 a = MkT68 (F68 a)+$(deriveAll1 ''T68)
+ tests/T80Spec.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++module T80Spec (main, spec) where++import Generics.Deriving.TH+import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec = return ()++newtype T f a b = MkT (f a b)+$(deriveAll1 ''T)
+ tests/T82Spec.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++#if __GLASGOW_HASKELL__ < 806+{-# LANGUAGE TypeInType #-}+#endif++module T82Spec (main, spec) where++import Test.Hspec++#if MIN_VERSION_base(4,10,0)+import Generics.Deriving.TH+import GHC.Exts (RuntimeRep, TYPE)++data Code m (a :: TYPE (r :: RuntimeRep)) = Code+$(deriveAll0And1 ''Code)+#endif++main :: IO ()+main = hspec spec++spec :: Spec+spec = return ()
+ tests/TypeInTypeSpec.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++#if __GLASGOW_HASKELL__ < 806+{-# LANGUAGE TypeInType #-}+#endif++module TypeInTypeSpec (main, spec) where++import Data.Proxy (Proxy(..))+import Generics.Deriving.TH+import Test.Hspec++#if MIN_VERSION_base(4,10,0)+import Generics.Deriving (Generic1(..))+#endif++data TyCon x (a :: x) (b :: k) = TyCon k x (Proxy a) (TyCon x a b)+$(deriveAll0And1 ''TyCon)++data family TyFam x (a :: x) (b :: k)+data instance TyFam x (a :: x) (b :: k) = TyFam k x (Proxy a) (TyFam x a b)+$(deriveAll0And1 'TyFam)++#if MIN_VERSION_base(4,10,0)+gen1PolyKinds :: Generic1 f => f 'True -> Rep1 f 'True+gen1PolyKinds = from1+#endif++main :: IO ()+main = hspec spec++spec :: Spec+spec = parallel $ do+#if MIN_VERSION_base(4,10,0)+ describe "TyCon Bool 'False 'True" $+ it "has an appropriately kinded Generic1 instance" $+ let rep :: Rep1 (TyCon Bool 'False) 'True+ rep = gen1PolyKinds $ let x = TyCon True False Proxy x in x+ in seq rep () `shouldBe` ()+ describe "TyFam Bool 'False 'True" $+ it "has an appropriately kinded Generic1 instance" $+ let rep :: Rep1 (TyFam Bool 'False) 'True+ rep = gen1PolyKinds $ let x = TyFam True False Proxy x in x+ in seq rep () `shouldBe` ()+#else+ return ()+#endif