In Haskell, is there a way to define a type constructor that includes a bunch of type constraints?

there. Relative Haskell newbie here. I have a big bunch of data types and functions on two type variables that require that the types are Eq, Ord, and Show. I found myself writing

type Foo n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => Bar n t -- and
data Baz n t where
  Baz :: (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => {
    f1 :: !n,
    f2 :: !t
  } -> Baz n t

all over the place.

Is there a way to write something like

type EqOrdShow d n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => d n t

such that I could write

type Foo n t = EqOrdShow Foo n t -- and
data Baz n t where
  Baz :: {f1 :: !n, f2 :: !t} -> EqOrdShow Baz n t

or some other way of giving a name to the list of constraints to avoid repeating it?

>Solution :

You can define an alias for the constraint:

type EqOrdShow n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t)

data Baz n t where
  Baz :: EqOrdShow n t => {f1 :: !n, f2 :: !t} -> Baz n t

I don’t think you can avoid having to write -> Baz something something explicitly at the end of the type of each constructor.


Also keep in mind that the record fields are not so useful here. For instance, the following won’t work

foo :: Baz n t -> String
foo x = show (f1 x)
-- No instance for (Show n) arising from a use of `show'

since only pattern matching can bring the Show n constraint in scope. You’ll need to use something like

foo2 :: Baz n t -> String
foo2 Baz{f1=y} = show y

Leave a Reply