Feel free to change the title, I\'m just not experienced enough to know what\'s really going on.
So, I was writing a program loosely based on this, and wrote this (a
Constraints on a type variable can not be part of any Haskell type signature.
This may seem a bit of a ridiculous statement: "what's (==) :: Eq a => a -> a -> a
then?"
The answer is that a
doesn't really exist, in much the same way there is not really an x
in the definition f x = x * log x
. You've sure enough used the x
symbol in defining that function, but really it was just a local tool used in the lambda-abstraction. There is absolutely no way to access this symbol from the outside, indeed it's not required that the compiler even generates anything corresponding to x
in the machine code – it might just get optimised away.
Indeed, any polymorphic signature can basically be read as a lambda expression accepting a type variable; various writing styles:
(==) :: forall a . Eq a => a -> a -> a
(==) :: ∀ a . Eq a => a -> a -> a
(==) :: Λa. {Eq a} -> a -> a -> a
This is called System F.
Note that there is not really a "constraint" in this signature, but an extra argument: the Eq
-class dictionary.
Usually you want to avoid having constraints in your type synonyms unless it's really necessary. Take the Data.Set
API from containers
for example.
Many operations in Data.Set
require the elements of the set to be instances of Ord
because Set
is implemented internally as a binary tree. member
or insert
both require Ord
member :: Ord a => a -> Set a -> Bool
insert :: Ord a => a -> Set a -> Set a
However the definition of Set
doesn't mention Ord
at all.
This is because some operations on Set
dont require an Ord
instance, like size
or null
.
size :: Set a -> Int
null :: Set a -> Bool
If the type class constraint was part of the definition of Set
, these functions would have to include the constraint, even though it's not necessary.
So yes, it is possible to have constraints in type synonyms using RankNTypes
, but it's generally ill-advised. It's better to write the constraint for the functions that need them instead.