Reputation: 902
Is it possible to define a generic type class instance parameterized by a type a
in Haskell?
For example:
data Box a = Box a deriving Show
class Boxable a where
create :: a -> Box a
-- pseudo syntax here
instance forall a . Boxable a where
create = Box
If no, why not?
I am aware of the fact that this example is rather simple and "useless". I just want to know whether this is theoretically possible, not whether its practically relevant.
Upvotes: 2
Views: 134
Reputation: 120711
Your code is literally legal Haskell, nothing “pseudo syntax” about it. It's not quite Haskell98, but with two very harmless syntactic extensions it does compile:
{-# LANGUAGE ExplicitForall, FlexibleInstances #-}
data Box a = Box a deriving Show
class Boxable a where
create :: a -> Box a
instance forall a . Boxable a where
create = Box
The -XExplicitForall
† is required for the explicit forall
(duh), but actually you don't even need this because Haskell type variables are by default universally quantified:
{-# LANGUAGE FlexibleInstances #-}
instance Boxable a where
create = Box
Except, like chepner already commented this doesn't really make sense, because now create
behaves just like a regular parametric function without any typeclass needed:
create' :: a -> Box a
create' = Box
That said, such once-and-for-all instances can actually be useful, if you constrain them with some superclass:
class Foo a
class Bar a
class (Foo a, Bar a) => FooBar a
instance (Foo a, Bar a) => FooBar a
Now if you mention FooBar (someComplicatedType)
in a function's constraints, it has the same effect as writing out (Foo (someComplicatedType), Bar (someComplicatedType)
, which can significantly de-clunk your code and error messages and also make your projects more future-safe, because you can add or remove superclasses to FooBar
without changing the signatures of all the functions that have this constraint.
(A very similar thing can be achieved with -XConstraintKinds
as the arguably more straightforward constraint synonym type FooBar a = (Foo a, Bar a)
, but this brings in the well-known problem that type
isn't really an encapsulation at all but can be unravelled by the compiler at any time, which isn't normally much of a problem except it leads to much more confusing type error messages.)
†You won't find -XExplicitForall
itself very often in Haskell files, because it's only really needed as part of either -XScopedTypeVariables
or -XRankNTypes
, both of which are common and enable the forall
keyword, or ∀
as I prefer to write it (which additionally requires -XUnicodeSyntax
).
Upvotes: 5