Code Monkey home page Code Monkey logo

derive's Introduction

Derive Hackage version Build Status

Warning: This package has no official maintainer anymore. Use at your own risk. You may wish to consider the built-in mechanism GHC.Generics or libraries such as generic-deriving.

Data.Derive is a library and a tool for deriving instances for Haskell programs. It is designed to work with custom derivations, SYB and Template Haskell mechanisms. The tool requires GHC, but the generated code is portable to all compilers. We see this tool as a competitor to DrIFT.

This document proceeds as follows:

  • Obtaining and Installing Data.Derive
  • Supported Derivations
  • Using the Derive Program
  • Using Template Haskell Derivations
  • Writing a New Derivation

Acknowledgements

Thanks to everyone who has submitted patches and given assistance, including: Twan van Laarhoven, Spencer Janssen, Andrea Vezzosi, Samuel Bronson, Joel Raymont, Benedikt Huber, Stefan O'Rear, Robin Green, Bertram Felgenhauer.

Obtaining and Installing Data.Derive

Installation follows the standard pattern of any Haskell library or program, type cabal update to update your local hackage database, then cabal install derive to install Derive.

Supported Derivations

Data.Derive is not limited to any prebuild set of derivations, see later for howto add your own. Out of the box, we provide instances for the following libraries.

Using the Derive program

Let's imagine we've defined a data type:

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Eq, Show)

Now we wish to extend this to derive Binary and change to defining Eq using our library. To do this we simply add to the deriving clause.

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Show {-! Eq, Binary !-})

Or alternatively write:

{-!
deriving instance Eq Color
deriving instance Binary Color
!-}

Now running derive on the program containing this code will generate appropriate instances. How do you combine these instances back into the code? There are various mechanisms supported.

Appending to the module

One way is to append the text to the bottom of the module, this can be done by passing the --append flag. If this is done, Derive will generate the required instances and place them at the bottom of the file, along with a checksum. Do not modify these instances.

As a GHC preprocessor

To use Derive as a GHC preprocessor, add the following line at the top of the source file:

{-# OPTIONS_GHC -F -pgmFderive -optF-F #-}

This instructs GHC to apply a preprocessor (-F), and to use the preprocessor derive -F.

Using CPP

One way is to use CPP. Ensure your compiler is set up for compiling with the C Pre Processor. For example:

{-# LANGUAGE CPP #-}
{-# OPTIONS_DERIVE --output=file.h #-}

module ModuleName where

#include "file.h"

Side-by-side Modules

If you had Colour.Type, and wished to place the Binary instance in Colour.Binary, this can be done with:

{-# OPTIONS_DERIVE --output=Binary.hs --module=Colour.Binary --import #-}

Here you ask for the output to go to a particular file, give a specific module name and import this module. This will only work if the data structure is exported non-abstractly.

Using Template Haskell Derivations

One of Derive's advantages over DrIFT is support for Template Haskell (abbreviated TH). Derive can be invoked automatically during the compilation process, and transparently supports deriving across module boundaries. The main disadvantage of TH-based deriving is that it is only portable to compilers that support TH; currently that is GHC only.

To use the TH deriving system, with the same example as before:

{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH
import Data.Binary

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Show)

$( derive makeEq ''Color )
$( derive makeBinary ''Color )

We need to tell the compiler to insert the instance using the TH splice construct, $( ... ) (the spaces are optional). The splice causes the compiler to run the function derive (exported from Data.DeriveTH), passing arguments makeFooBar and ''Color. The second argument deserves more explanation; it is a quoted symbol, somewhat like a quoted symbol in Lisp and with deliberately similar syntax. (Two apostrophes are used to specify that this name is to be resolved as a type constructor; just 'Color would look for a data constructor named Color.)

Writing a New Derivation

There are two methods for writing a new derivation, guessing or coding. The guessing method is substantially easier if it will work for you, but is limited to derivations with the following properties:

  • Inductive - each derivation must be similar to the previous one. Binary does not have this property as a 1 item derivation does not have a tag, but a 2 item derivation does.
  • Not inductive on the type - it must be an instance for the constructors, not for the type. Typeable violates this property by inducting on the free variables in the data type.
  • Not type based - the derivation must not change based on the types of the fields. Play and Functor both behave differently given differently typed fields.
  • Not record based - the derivation must not change on record fields. Show outputs the fields, so this is not allowed.

If however your instance does meet these properties, you can use derivation by guess. Many instances do meet these conditions, for examples see: Eq, Ord, Data, Serial etc. If however you need to code the derivation manually see examples such as Update and Functor.

Modifying Derive

The standard sequence for testing Derive is:

$ ghci Main.hs
:main --generate
:reload
:main --test

The --generate option will automatically generate DSL's for derivations derived by example. The --test option runs all test comparisons and then loads the file with Template Haskell.

Coding a new derivation

My best suggestion, start with a similar instance, i.e. to make Eq2 from Eq do:

  • Copy Data/Derive/Eq.hs to Data/Derive/Eq2.hs
  • Rename some of the bits in Eq2.hs from Eq
  • ghci -- load derive
  • :main --generate -- this adds Eq2.hs to the .cabal/All.hs files etc
  • :reload -- reload with Eq2.hs

Now fix up Eq2.hs appropriately.

derive's People

Contributors

danielschuessler avatar duog avatar fuuzetsu avatar h4ck3rm1k3 avatar ip1981 avatar jwaldmann avatar lemmih avatar ndmitchell avatar samb avatar sorear avatar spencerjanssen avatar strake avatar thoughtpolice avatar twanvl avatar vshabanov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

derive's Issues

Fails to build under newest derive

[50 of 62] Compiling Data.Comp.Derive ( src/Data/Comp/Derive.hs, dist/build/Data/Comp/Derive.o )

src/Data/Comp/Derive.hs:73:24: Not in scope: ‘A.makeFunctor’


This wouldn't be such a large problem, except that I failed to install an old derive, because it requires an old mtl

Could not convert Type to Kind () ConT GHC.Types.Nat

Derive 2.6.2 running under ghc 8.0.2 reports the following error:

BitR.hs:1:1: error:
    Exception when trying to run compile-time code:
      Could not convert Type to Kind ()
ConT GHC.Types.Nat
derive/v2_6_2/src/Language/Haskell/Convert.hs:(305,5)-(306,57): Non-exhaustive patterns in function conv

CallStack (from HasCallStack):
derive/v2_6_2/src/Language/Haskell/Convert.hs:22:87 in derive:Language.Haskell.Convert
    Code: derive makeNFData ''UInt

When processing the code below:

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE KindSignatures #-}

import GHC.TypeLits
import Control.DeepSeq(NFData(rnf))
import Data.DeriveTH

newtype Bit (n :: Nat) = Bit { unBit :: Integer }
    deriving (Eq, Ord)

instance (KnownNat n) => NFData (Bit n) where rnf (Bit i) = rnf i

newtype UInt n = UInt (Bit n)
$(derive makeNFData ''UInt)

TH derivation doesn't work when the type name is qualified

Let's try to derive Arbitrary for Maybe, but imported qualified from Prelude:

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell   #-}

import           Data.DeriveTH   (derive, makeArbitrary)
import qualified Prelude         as P

import           Test.QuickCheck (Arbitrary (..))

derive makeArbitrary ''P.Maybe

It won't work:

    Not in scope: type constructor or class ‘Maybe’
    Perhaps you meant ‘P.Maybe’ (imported from Prelude)
    Not in scope: type constructor or class ‘Int’
    Perhaps you meant ‘P.Int’ (imported from Prelude)

When I run GHC with -ddump-splices, I see that derive generates the following code (which doesn't include qualified names):

    derive makeArbitrary ''P.Maybe
  ======>
    instance Arbitrary a_3530822107858468866 =>
             Arbitrary (Maybe a_3530822107858468866) where
      arbitrary
        = do { x <- choose (0 :: Int, 1);
               case x of {
                 0 -> return Nothing
                 1 -> do { x1 <- arbitrary;
                           return (Just x1) }
                 _ -> error "FATAL ERROR: Arbitrary instance, logic bug" } }

Use cabal's test-suite section

It'd be great if the package could use cabal-supported tests: the existing way is quite inconvenient to run and cabal is not informed about the test dependencies that we need (json, QuickCheck, binarydefer, cereal). It also makes it very difficult to test the project inside a cabal sandbox.

Could not convert Type to Type ()

Running derive/v2_6_2 with GHC8 I'm getting this error:

Bug3.hs:1:1: error:
    Exception when trying to run compile-time code:
      Could not convert Type to Type ()
LitT (NumTyLit 8)
v2_6_2/src/Language/Haskell/Convert.hs:(103,5)-(114,29): Non-exhaustive patterns in function conv

CallStack (from HasCallStack):
v2_6_2/src/Language/Haskell/Convert.hs:22:87 in derive:Language.Haskell.Convert
    Code: derive makeNFData ''Foo

for the code below:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TemplateHaskell #-}

import Control.DeepSeq(NFData(..))
import Data.DeriveTH
import GHC.TypeLits

newtype Vec (n :: Nat) a = Vec [a]

data Foo x = Bar (Vec 8 Bool) | Baz x
$(derive makeNFData ''Foo)

Errors while using C and GHC preprocessors

I'm on ghc 8.0.1 (stackage nightly-2016-07-07) and i'm trying to use derive for Arbitrary, Uniplate and Biplate. I tried both preprocessors, the error message does not give me enough information to figure out why they don't work.

With cpp https://github.com/ndmitchell/derive#using-cpp

» stack build --ghc-options '-rtsopts -fprof-auto -fprof-auto-calls -fprof-cafs' --executable-profiling 
vhdl-0.1.0.0: build
Preprocessing executable 'vhdl' for vhdl-0.1.0.0...

/home/flip111/haskell/vhdl/src/Main.hs:14:0: error:
     fatal error: file.h: No such file or directory
     #include "file.h"
     ^
compilation terminated.
`gcc' failed in phase `C pre-processor'. (Exit code: 1)

--  While building package vhdl-0.1.0.0 using:
      /home/flip111/.stack/setup-exe-cache/x86_64-linux/setup-Simple-Cabal-1.24.0.0-ghc-8.0.1 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.0.0 build exe:vhdl --ghc-options " -ddump-hi -ddump-to-file"
    Process exited with code: ExitFailure 1

with ghc preprocessor https://github.com/ndmitchell/derive#as-a-ghc-preprocessor

» stack build --ghc-options '-rtsopts -fprof-auto -fprof-auto-calls -fprof-cafs' --executable-profiling
vhdl-0.1.0.0: configure
Configuring vhdl-0.1.0.0...
vhdl-0.1.0.0: build
Preprocessing executable 'vhdl' for vhdl-0.1.0.0...
derive: Don't know how to derive type class: Generic
CallStack (from HasCallStack):

  error, called at src/Derive/Derivation.hs:75:0: error:
    59 in derive-2.5.26-D3fLjLIsNAEmHqh8OJSQ3:Derive.Derivation
`derive' failed in phase `Haskell pre-processor'. (Exit code: 1)

--  While building package vhdl-0.1.0.0 using:
      /home/flip111/.stack/setup-exe-cache/x86_64-linux/setup-Simple-Cabal-1.24.0.0-ghc-8.0.1 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.0.0 build exe:vhdl --ghc-options " -ddump-hi -ddump-to-file"
    Process exited with code: ExitFailure 1

support haskell-src-exts-1.21+?

This is not urgent at all, but just a heads-up that since derive-2.6.5 does not build with haskell-src-exts-1.21 (lts-14), the package will probably get dropped from Fedora 32 or later.

src/Language/Haskell.hs:286:29: error:
    Not in scope: data constructor ‘KindStar’
    |
286 |           f (KindedVar _ x (KindStar _)) = Just $ prettyPrint x
    |                             ^^^^^^^^

Anyway it might be good to add it to Stackage if you plan to continue maintaining it actively, otherwise it is fine I guess. :)

quickcheck's arbitrary derivation is bad for data types mostly with recursive constructors

From https://code.google.com/p/ndmitchell/issues/detail?id=561

Let's define a datatype for expressions

data Expr = Plus Expr Expr |
Minus Expr Expr |
Times Expr Expr |
Divide Expr Expr |
Number Integer

The derived instance has the same probabilty of every constructor.

So the probability for a recursive constructor is 4/5 and the probability of a nonrecursive one is 1/5.

When using quickcheck it generates random data structures using this function. When the probability is like that I noticed that most checks loop, because they build a super big tree, with so many nodes, that the probability of finishing it is near zero.

I was thinking of a solution and a fast hackish solution would be to just distribute the sum of 1/2 probability to all nonrecursive constructors, and 1/2 among all other constructors (or just check the constants using a few thousand checks on some tree size counting function).

A better solution would need a piece of paper and a pen and a probability wikipedia page.

Doesn't compile with 7.9

There were some changes in Template Haskell API.

I made a pull request with a fix to the same problem to aeson already, you can have a look at it here. I'm using GHC-7.9.20140308

Configuring derive-2.5.13...
Building derive-2.5.13...
Preprocessing library derive-2.5.13...
[ 1 of 65] Compiling Language.Haskell.TH.Compat ( Language/Haskell/TH/Compat.hs, dist/dist-sandbox-c4fc5f8b/build/Language/Haskell/TH/Compat.o )

Language/Haskell/TH/Compat.hs:31:23:
    Not in scope: data constructor ‘ClassP’
    Perhaps you meant one of these:
      ‘ClassD’ (imported from Language.Haskell.TH),
      ‘ClassI’ (imported from Language.Haskell.TH),
      ‘Clause’ (imported from Language.Haskell.TH)

Language/Haskell/TH/Compat.hs:32:25:
    Not in scope: data constructor ‘ClassP’
    Perhaps you meant one of these:
      ‘ClassD’ (imported from Language.Haskell.TH),
      ‘ClassI’ (imported from Language.Haskell.TH),
      ‘Clause’ (imported from Language.Haskell.TH)

Language/Haskell/TH/Compat.hs:33:11:
    Not in scope: data constructor ‘ClassP’
    Perhaps you meant one of these:
      ‘ClassD’ (imported from Language.Haskell.TH),
      ‘ClassI’ (imported from Language.Haskell.TH),
      ‘Clause’ (imported from Language.Haskell.TH)
Failed to install derive-2.5.13

Example in Data.Derive.UniplateDirect fails

{-# OPTIONS_GHC -F -pgmFderive -optF-F -optF-F #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

import Data.Derive.UniplateDirect
import Data.Generics.Uniplate.Direct

data Foo a = Foo a (Bool, a)

{-!
deriving instance UniplateDirect (Foo Int)
deriving instance UniplateDirect (Bool, Int) Int
deriving instance UniplateDirect (Foo Int) Int
!-}

When loaded or compiled:

λ> :load "/tmp/test.hs"
[    1 of 1] Compiling Main             ( /tmp/test.hs, interpreted )

/tmp/ghced76_0/ghc_11.hspp:17:10: error:
    • Expecting one fewer argument to ‘Uniplate Foo’
      Expected kind ‘* -> Constraint’,
        but ‘Uniplate Foo’ has kind ‘Constraint’
   • In the instance declaration for ‘Uniplate Foo Int’

/tmp/ghced76_0/ghc_11.hspp:17:19: error:
    • Expecting one more argument to ‘Foo’
      Expected a type, but ‘Foo’ has kind ‘* -> *’
    • In the first argument of ‘Uniplate’, namely ‘Foo’
      In the instance declaration for ‘Uniplate Foo Int’

/tmp/ghced76_0/ghc_11.hspp:25:10: error:
    • Expecting one fewer argument to ‘Biplate Int Foo’
      Expected kind ‘* -> Constraint’,
        but ‘Biplate Int Foo’ has kind ‘Constraint’
    • In the instance declaration for ‘Biplate Int Foo Int’

/tmp/ghced76_0/ghc_11.hspp:25:22: error:
    • Expecting one more argument to ‘Foo’
      Expected a type, but ‘Foo’ has kind ‘* -> *’
    • In the second argument of ‘Biplate’, namely ‘Foo’
      In the instance declaration for ‘Biplate Int Foo Int’
Failed, modules loaded: none.

2.5.19 introduced kind mismatch error into another program

Please see lamdu/lamdu#27
code like

{-# LANGUAGE KindSignatures, TemplateHaskell, DeriveFunctor, DeriveFoldable, DeriveTraversable, GeneralizedNewtypeDeriving, DeriveDataTypeable, RankNTypes #-}
-- hopefully didn't cut something important to understanding
Lens.makeLenses ''Scope
derive makeMonoid ''Scope

produces kind mismatch error using derive 2.5.19

Lamdu/Sugar/Types.hs:491:1:
    The second argument of ‘Scope’ should have kind ‘* -> *’,
      but ‘m_1628154822’ has kind ‘*’
    In the instance declaration for
      ‘Monoid (Scope name_1628154821 m_1628154822)’

but works using 2.5.18.

Could not convert Dec to Decl ()

Running derive/v2_6_2 with GHC8 I'm getting this error:

Bug2.hs:1:1: error:
    Exception when trying to run compile-time code:
      Could not convert Dec to Decl ()
TySynD Main.NewType [] (ConT Main.DataType)
derive/v2_6_2/src/Language/Haskell/Convert.hs:(41,14)-(45,8): Non-exhaustive patterns in case

CallStack (from HasCallStack):
derive/v2_6_2/src/Language/Haskell/Convert.hs:22:87 in derive:Language.Haskell.Convert
    Code: derive makeNFData ''NewType

for the code below:

{-# LANGUAGE TemplateHaskell #-}

import Control.DeepSeq(NFData(..))
import Data.DeriveTH

type NewType = DataType
data DataType = DataType
$(derive makeNFData ''NewType)

Admittedly deriving something for a type is not exactly the best idea, but a more helpful error would be nice.

Find another maintainer

I don't use the project myself, with the several programmable type-class features in GHC it's less important, and the projects which would have a serious need for this kind of thing (e.g. lens) contain the code themselves. To remain relevant and useful some thought should probably be given to exactly what derive should do, and how it should do it, and given I have no itch to scratch, I'm the wrong person to do it.

On the flip side, there are 67 reverse dependencies, so it's a fairly well-used project. I'll keep up with bug fixes for the time being, but aim to find an alternative maintainer (or co-maintainer to start with). This ticket is to write a blog post for that.

to decrease build time, sources should be in separate src/ folder

The derive.cabal spec contains executable and library. When cabal install, (most) library files are recompiled. This wastes time.

The executable should depend on the library, then recompilation is avoided.
This only works when the sources are in a separate directory.

(I don't know why, and I think this is seriously underdocumented, but I know it from experience.)

It is a trivial change to make, I can do it.

Parse Fails For pattern aliases (MINOR: see issue comments)

When I run derive on a file contianing a pattern alias, it blows up.

I cloned built derive off of master to confirm this problem still exists in git. The version string output is as follows:

[2089] derive$ stack exec -- derive --version
Derive 2.5.* (C) Neil Mitchell 2006-2013

The problem can be reproduced by:

[2090] derive$ stack exec -- derive ./Minimal.hs 
derive: fromParseResult: Parse failed at [./Minimal.hs] (3:5): Parse error: rec
CallStack (from HasCallStack):
  error, called at src/Language/Haskell/Exts/ParseMonad.hs:83:41 in haskell-src-exts-1.18.2-Kjop5wIioOPX4MdOWk71u:Language.Haskell.Exts.ParseMonad

Where Minimal.hs is

module Minimal where

foo rec@a = a

Now the really odd thing is that when I load haskell-src-exts-1.19.1 (the version I compiled derive against) and call parseFile on that same Minimal.hs file, the parse seems to go fine.

λ> import Language.Haskell.Exts
λ> parseFile "/home/ethan/Downloads/derive/Minimal.hs"
ParseOk (Module (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 1 4 1, srcInfoPoints = [SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 1 1 1,SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 1 1 1,SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 1 3 1,SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 4 1 4 1,SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 4 1 4 1]}) (Just (ModuleHead (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 1 1 21, srcInfoPoints = [SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 1 1 7,SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 16 1 21]}) (ModuleName (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 1 8 1 15, srcInfoPoints = []}) "Minimal") Nothing Nothing)) [] [] [FunBind (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 1 3 14, srcInfoPoints = []}) [Match (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 1 3 14, srcInfoPoints = []}) (Ident (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 1 3 4, srcInfoPoints = []}) "foo") [PAsPat (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 5 3 10, srcInfoPoints = [SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 8 3 9]}) (Ident (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 5 3 8, srcInfoPoints = []}) "rec") (PVar (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 9 3 10, srcInfoPoints = []}) (Ident (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 9 3 10, srcInfoPoints = []}) "a"))] (UnGuardedRhs (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 11 3 14, srcInfoPoints = [SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 11 3 12]}) (Var (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 13 3 14, srcInfoPoints = []}) (UnQual (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 13 3 14, srcInfoPoints = []}) (Ident (SrcSpanInfo {srcInfoSpan = SrcSpan "/home/ethan/Downloads/derive/Minimal.hs" 3 13 3 14, srcInfoPoints = []}) "a")))) Nothing]])

This problem happened both after a clean checkout and after I bumped the version constraint on haskell-src-exts to >= 1.19.0. I generated a stack.yaml file with stack init so that you can have a clearer view of the rest of my build environment if you are interested I've pasted the contents here: https://pastebin.com/i5yd5qhY.

"derive makeArbitrary" error w/ strict types (8.0.1)

data NoteListItem = NoteListItem {
      noteListItemId     :: !Text
    , noteListItemHash   :: !Text
    , noteListItemTitle  :: !Text
    , noteListItemLength :: !Int
    , noteListItemCreatedAt :: !UTCTime
    , noteListItemUpdatedAt :: !UTCTime
    } deriving (Show, Eq, Data, Typeable, Generic, Ord)


$(derive makeArbitrary ''NoteListItem)


Exception when trying to run compile-time code:
      Could not convert (Bang,Type) to Type
(Bang NoSourceUnpackedness SourceLazy,ConT Data.Text.Internal.Text)
src/Language/Haskell/Convert.hs:(76,5)-(79,64): Non-exhaustive patterns in function conv

CallStack (from HasCallStack):
  error, called at src/Language/Haskell/Convert.hs:20:87 in derive-2.5.25-6jyS0d772bZHapQdVyiucF:Language.Haskell.Convert
    Code: derive makeArbitrary ''NoteListItem

The Read instance requires excessive brackets

A user reports they are facing one issue while using makeRead derivation on a user defined data structure.

Here is my data structure :

data EFGH               = EF ABCD
                                   | GH ABCD
                                      deriving (Data, Show, Read, Typeable)

data ABCD               = AB Int
                                    | CD
                                     deriving (Data, Show, Read, Typeable)

I assigned some values though a function and tried to show the data structure.

Example 1 - Output of Show -: EF (AB 10)
Example 2 - Output of Show -: GH CD

In this case while I tried to Read Example 1 and Example 2 into data structure EFGH, works correctly.

But here is the failure case :

data EFGH         = EF ABCD
                             | GH ABCD
                                 deriving (Data, Typeable)

data ABCD         = AB Int
                        | CD
                                deriving (Data, Typeable)

$(derive makeShow ''EFGH)
$(derive makeRead ''EFGH)
$(derive makeShow ''ABCD)
$(derive makeRead ''ABCD)

Example 1 - Output of Show -: EF (AB 10)
Example 2 - Output of Show -: GH CD

In this TH derivation example 1 can be Read into EFGH succesfully, but Example 2 could not be Read into EFGH.

I got the following error : TestRSeq: Prelude.read: no parse

But if put a bracket around the inner constructor it works fine.

GH CD -> GH (CD)

makeRead derivation type can read it succesfully.

Could not convert Dec to Decl

Hi Neil or hi new maintainer,

I've trying to derive some type automatically using this fantastic tool. For simple examples it works fine, but when I get it into "real life", I'm getting this error constantly. I've been googling and somewhere someone says that this is a bug in your code. Is this true?

 Exception when trying to run compile-time code:
      Could not convert Dec to Decl
TySynD RulesLib.CStatAnn [] (AppT (ConT Language.C.Syntax.AST.CStatement) (AppT (AppT (ConT RulesLib.Annotation) (ConT Language.C.Data.Node.NodeInfo)) (ConT RulesLib.NodeProperties)))
src/Language/Haskell/Convert.hs:(39,14)-(49,8): Non-exhaustive patterns in case


    Code: derive makeBinary ''CStatAnn

Thanks in advance
Salva

Derived functor context has type variable mismatch

I'm trying to use Data.Derive.Functor to derive an instance for a data type with a type variable of kind * -> *:

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Test where

import Data.Derive.Functor
import Data.DeriveTH

newtype WrappedFunctor f a = WrapFunctor (f a)

$(derive makeFunctor ''WrappedFunctor)

This fails to compile, but running it yields a little insight:

Lol.hs:10:3-37: Splicing declarations
    derive makeFunctor ''WrappedFunctor
  ======>
    instance Functor f_1627394097 => Functor (WrappedFunctor t1) where
      fmap _f (WrapFunctor a1) = WrapFunctor (fmap _f a1)

Lol.hs:10:3:
    Variable ‘f_1627394097’ occurs more often than in the instance head
      in the constraint: Functor f_1627394097
    (Use UndecidableInstances to permit this)
    In the instance declaration for ‘Functor (WrappedFunctor t1)’
Failed, modules loaded: none.

The generated code is pretty close, except that the instance head uses t1 instead of f_1627394097.

Enum instances derived with TH crash with "Missing field in record construction

From https://code.google.com/p/ndmitchell/issues/detail?id=607

{-# LANGUAGE TemplateHaskell #-} module Main where

import Data.DeriveTH

data Foo = Bar | Baz deriving (Show, Enum)

data Quux = Quux Foo deriving (Show)

$(derive makeEnum ''Quux)

t :: Int -> Quux
t = toEnum

main = print $ map t [0, 1]

The code is expected to print [Quux Foo, Quux Bar] but crashes with "Missing field in record construction" message.

derive-2.5.11 with GHC 7.4.2.

Other methods seem broken too. fromEnum $ Quux Foo and fromEnum $ Quux Bar both evaluate to 0.

@ndmitchell replied: This is what I'd expect, but probably not what anyone else expects :). The idea is that given data Foo = A | B Int | C Int Int, it produces the enum values A, B | and C | |, where | ends up in a "missing field" message. The behaviour you are expecting is perfectly reasonable, so I'll leave this bug to:

  1. Document what Enum does, something that is currently lacking
  2. Add EnumNest, which does nested enums, and would work with Quux

Hackage distribution lacks TestInstances

I attempted to build a self-checking test based just on the contents of the tarball from Hackage and it fails with:
AutoGenerated_Test3.hs:7:8:
Could not find module `Derive.TestInstances'
Use -v to see a list of the files searched for.
*** Exception: Failed to typecheck results

Indeed the file is not there in the tarball:
% curl -O /dev/stdout https://hackage.haskell.org/package/derive-2.6.3/derive-2.6.3.tar.gz | tar ztf - | grep Derive.TestInstances
curl: (3) malformed
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 53652 0 53652 0 0 77005 0 --:--:-- --:--:-- --:--:-- 76975

Build failure with GHC 8.2

[47 of 54] Compiling Language.Haskell.TH.Compat ( src/Language/Haskell/TH/Compat.hs, dist/build/Language/Haskell/TH/Compat.o )

src/Language/Haskell/TH/Compat.hs:26:66: error:
    • Couldn't match type ‘DerivClause’ with ‘Type’
      Expected type: [Type]
        Actual type: [DerivClause]
    • In the second argument of ‘map’, namely ‘cxt’
      In the expression: map from_cxt cxt
      In an equation for ‘dataDefinitionTypeArgs’:
          dataDefinitionTypeArgs (DataD _cx name _ _ _ cxt)
            = map from_cxt cxt
   |
26 | dataDefinitionTypeArgs (DataD _cx name _ _ _ cxt) = map from_cxt cxt
   |                                                                  ^^^

src/Language/Haskell/TH/Compat.hs:27:68: error:
    • Couldn't match type ‘DerivClause’ with ‘Type’
      Expected type: [Type]
        Actual type: [DerivClause]
    • In the second argument of ‘map’, namely ‘cxt’
      In the expression: map from_cxt cxt
      In an equation for ‘dataDefinitionTypeArgs’:
          dataDefinitionTypeArgs (NewtypeD cx name _ _ _ cxt)
            = map from_cxt cxt
   |
27 | dataDefinitionTypeArgs (NewtypeD cx name _ _ _ cxt) = map from_cxt cxt
   |                                   

breakage with template-haskell-2.11 (in ghc-8)

There is serious breakage due to the changes described in https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#template-haskell-2.11.0.0

While one can put the occasional _ in some patterns (for the additional "kind" argument), fixity information is gone, and needs to be reified (in Q), so instance Ppr Info from Language.Haskell.TH.FixedPpr cannot be repaired locally (I think).

I tried, because I have some legacy code that uses derive. Well, I guess in the long run I have to rewrite that code (to not use derive).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.