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