# Type class and instance declarations

Silver supports ad-hoc polymorphism via type classes. These are closely modeled on type classes in languages such as Haskell.

```
class Eq a {
eq :: (Boolean ::= a a) = \ x::a y::a -> !(x != y);
neq :: (Boolean ::= a a) = \ x::a y::a -> !(x == y);
}
instance Eq Integer {
eq = eqInteger;
neq = neqInteger;
}
instance Eq Float {
eq = eqFloat;
}
```

`Eq`

is a type class in the standard library, providing the functions `eq`

and `neq`

(the `==`

and `!=`

operators forward to calls to these functions.) Implementations of these functions are provided for various types by defining *instances*. The `Eq`

type class provides defaults for both of these methods, such that instances need only provide an implementation for one function or the other.

Type classes may be used as constraints on variables in type signatures; any constraints on a function’s type must be resolved in order to use the function. The members of a type class automatically have the declared class as a constraint; for example in type checking `eq(42, 128)`

the constraint `Eq Integer`

must be resolved, by looking up that instance.

Function and production signatures can also introduce type constraints, allowing type class members to be used with polymorphic types:

```
function allEqual
Eq a => Boolean ::= xs::[a]
{
return
case xs of
| h1 :: h2 :: t -> h1 == h2 && allEqual(h2 :: t)
| _ -> true
end;
}
```

Instances can also have type constraints:

```
instance Eq a => Eq [a] {
eq = \ x::[a] y::[a] -> length(x) == length(y) && all(zipWith(eq, x, y));
neq = \ x::[a] y::[a] -> length(x) != length(y) || any(zipWith(neq, x, y));
}
instance Eq a => Eq Maybe<a> {
eq = \ x::Maybe<a> y::Maybe<a> ->
case x, y of
| just(w), just(z) -> w == z
| nothing(), nothing() -> true
| _, _ -> false
end;
}
instance Eq a, Eq b => Eq Pair<a b> {
eq = \ x::Pair<a b> y::Pair<a b> -> x.fst == y.fst && x.snd == y.snd;
neq = \ x::Pair<a b> y::Pair<a b> -> x.fst != y.fst || x.snd != y.snd;
}
```

To satisfy any of these instances, the constraints on the matched instance must be satisfied as well. For example `eq([42], [42])`

would need to satisfy `Eq [Integer]`

, which matches the instance `Eq [a]`

, in turn giving the constraint `Eq Integer`

that must be satisfied.

Type classes can extend existing type classes with additional members:

```
class Eq a => Ord a {
compare :: (Integer ::= a a) = \ x::a y::a ->
if x == y then 0 else if x <= y then -1 else 1;
lt :: (Boolean ::= a a) = \ x::a y::a -> compare(x, y) < 0;
lte :: (Boolean ::= a a) = \ x::a y::a -> compare(x, y) <= 0;
gt :: (Boolean ::= a a) = \ x::a y::a -> compare(x, y) > 0;
gte :: (Boolean ::= a a) = \ x::a y::a -> compare(x, y) >= 0;
}
instance Ord Integer {
compare = \ x::Integer y::Integer -> x - y;
lt = ltInteger;
lte = lteInteger;
gt = gtInteger;
gte = gteInteger;
}
instance Ord a => Ord [a] {
lte = \ x::[a] y::[a] ->
case x, y of
| h1::t1, h2::t2 -> h1 <= h2 && t1 <= t2
| [], _ -> true
| _, _ -> false
end;
}
```

Here the `Ord`

type class extends `Eq`

. Any constraint `Ord a`

implicitly also adds a constraint for `Eq a`

, and any instance of `Ord`

must have a corresponding instance of `Eq`

for the same type.

Type classes can be defined for higher-kinded types. For example, the `Functor`

type class has kind `* -> *`

:

```
class Functor (f :: * -> *) {
map :: (f<b> ::= (b ::= a) f<a>);
}
instance Functor [] {
map = \ f::(b ::= a) l::[a] ->
if null(l) then []
else f(head(l)) :: map(f, tail(l));
}
instance Functor Maybe {
map = \ f::(b ::= a) m::Maybe<a> ->
case m of
| just(x) -> just(f(x))
| nothing() -> nothing()
end;
}
```

Sometimes a general instance may match a type, but fail to match the instance’s type constraints. This can lead to rather confusing error messages, thus it is sometimes helpful to specify a more specific instance that always fails with nicer error message:

```
instance typeError "Decorated types do not support equality" => Eq Decorated a with i {
eq = error("type error");
}
```