2

I have a data type :

data BuildException a = KillBuild JobID a Stage
                      | FailBuild JobID a Stage
                      | CancelBuild JobID a Stage
                      | StopBuild JobID a Stage
                         deriving Typeable

where a has to have an instance for class Foo. I remember reading (in RWH, maybe) that while it was possible to have class constraints in a data definition, it was not desirable. What's the proper way to do this then?

  • 1
    As a side note, you might like to split this type in two: `data Reason = Kill | Fail | Cancel | Stop; data BuildException a = BuildException Reason JobID a Stage`. – Daniel Wagner Jul 20 '12 at 20:24
  • @DanielWagner Yup just did that. –  Jul 20 '12 at 20:25

2 Answers2

5

Simply apply the type constraints on functions that need it. For example:

makeException :: Foo a => String -> BuildException a

There might even be some functions that don't need the Foo constraint, which might make it possible for the client of your API to use a subset of it without having to define the Foo constraint! That wouldn't be possible if it was part of the data record definition.

dflemstr
  • 25,947
  • 5
  • 70
  • 105
  • 2
    An example of not adding the constraint on every function can be found in several parts of the containers library. To take [Set](http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-Set.html) as an example, for its implementation it needs the `Ord` constraint the elements. Though various functions don't need such constraint, you can create an empty and single element set without and several 'process all elements' functions don't need it either. – Laar Jul 20 '12 at 19:58
0

You read correctly. However, in Haskell 2010, this feature was removed because it was useless. You could specify the constraint in the data type, but all functions also had to have the same constraint so there was really no point. Thus, the feature was removed because it was completely useless.

As said, you should just specify the constraints in the function. However, you should realize that you need not specify the constraint for a function that does not need it. In particular, creation functions don't necessarily need to be limited to the constraint if not necessary, because an unlimited function like that is a generalization of the constrained version. This applies to functions taking it as an argument, but such a function is much more likely to actually need the constraint.

alternative
  • 12,703
  • 5
  • 41
  • 41