pa-ba / compdata

Haskell library implementing "Data Types a la Carte"
http://hackage.haskell.org/package/compdata
Other
89 stars 27 forks source link

Type error using makeShowConstr on datatypes containing [a] #21

Open patrickt opened 7 years ago

patrickt commented 7 years ago

The following code:

data Literal a
  = Whole Integer
  | Real Double
  | Character Char
  | List [a]

derive [makeEqF, makeShowF, makeShowConstr] [''Literal]

encounters a type error during TH generation of the ShowConstr instance, to wit:

    • No instance for (Show a) arising from a use of ‘show’
      Possible fix:
        add (Show a) to the context of
          the type signature for:
            showConstr :: Literal a -> String
    • In the expression: show x_a6or
      In the second argument of ‘compdata-0.10.1:Data.Comp.Derive.Show.showCon'’, namely
        ‘[show x_a6or]’
      In the expression:
        compdata-0.10.1:Data.Comp.Derive.Show.showCon' "List" [show x_a6or]

This is running under GHC 8.01 (Stackage resolver lts-7.14).

emilaxelsson commented 7 years ago

The deriver has a simple heuristics that works for cases like:

data Exp a
    = Int Int
    | Add a a

where the constructors' arguments are either constant types or of type a. Any argument that is not of type a is assumed to be a constant type and will be shown as part of the constructor. That's why it tries to show the [a] argument.

It doesn't seem completely trivial to generalize makeShowConstr to your case (and in general to arbitrary functorial arguments, including nested). What should showConstr return for the List constructor?

patrickt commented 7 years ago

This is an excellent point. I had assumed that showConstr over an [a] argument would just punctuate and enclose the arguments in brackets, but upon reflection that doesn't make that much sense.

A friendlier, yet less-efficient, solution in my case would be to remove all occurrences of [a] and express lists with an additional functor data List a = Cons a a | Nil in the applicable signatures. I will probably not do this, though, as I'm running extremely large AST's through compdata, and was hoping someday to switch to Vectors for efficiency reasons.

My larger purpose is to have a coherent Render instance for the above Literal case, so that I can pass it to the lovely showTerm and writeHtmlTerm functions. I may just write a dummy ShowConstr instance and hand-code a Render instance here.

emilaxelsson commented 7 years ago

Yeah, that's probably best. But unless you need a custom Render instance for other reasons it should be enough to hand-code the ShowConstr instance.