114 lines
3.9 KiB
Markdown
114 lines
3.9 KiB
Markdown
+++
|
|
title = "`instance` declarations"
|
|
weight = 1
|
|
+++
|
|
|
|
A type can be declared as an instance of a class in two ways. The
|
|
general mechanism is the `instance` declaration; a convenient shortcut
|
|
that can sometimes be used is the `deriving` mechanism.
|
|
|
|
The general `instance` declaration grammar is the following:
|
|
|
|
```
|
|
topDefn ::= instance context => classId {type }where
|
|
{ {localDefn ; }}
|
|
```
|
|
|
|
This can be read as saying that the type *type* is an instance of class
|
|
*classId*, provided the constraints of *context* hold, and where the
|
|
*localDefn*'s specify the implementation of the methods of the class.
|
|
|
|
Sometimes, when a new type is defined using a `data` declaration, it can
|
|
simultaneously be made a member of certain useful, predefined classes,
|
|
allowing the compiler to choose the "obvious" implementation of the
|
|
class methods. This is done using the `deriving` qualification to a
|
|
`data` declaration (described in section
|
|
[4.1](fixme)) or to a
|
|
`struct` declaration (described in section
|
|
[4.2](fixme)). The only classes for which `deriving` can
|
|
be used for general types are `Bits`, `Eq` and `Bounded`. Furthermore,
|
|
`deriving` can be used for any class if the type is a data type that is
|
|
isomorphic to a type that has an instance for the derived class.
|
|
|
|
### Deriving `Bits` {#sec-deriving-Bits}
|
|
|
|
The instances derived for the `Bits` class can be described as follows:
|
|
|
|
- For a `struct` type it is simply the the concatenation of the bits for
|
|
all the fields. The first field is in the leftmost (most significant)
|
|
bits, and so on.
|
|
- For a `data` type, all values of the type occupy the same number of
|
|
bits, regardless of which disjunct (constructor) it belongs to. This
|
|
size is determined by the largest disjunct. The leftmost (most
|
|
significant) bits are a code (a tag) for the constructor. As few bits as
|
|
possible are used for this. The first constructor in the definition is
|
|
coded 0, the next constructor is coded 1, and so on. The size of the
|
|
rest of the bits is determined by the largest numbers of bits needed to
|
|
encode the fields for the constructors. For each constructor, the fields
|
|
are laid out left to right, and the concatenated bits are stored right
|
|
justified (*i.e.,* at the least significant bits). For disjuncts that
|
|
are smaller than the largest one, the bits between the constructor code
|
|
and the field bits, if any, are "don't care" bits.
|
|
|
|
Examples: The type
|
|
|
|
```hs
|
|
data Bool = False | True
|
|
```
|
|
|
|
uses one bit. `False` is represented by 0 and `True` by 1.
|
|
|
|
```hs
|
|
struct Två = { första :: Bit 8; andra:: Bit 16 }
|
|
```
|
|
|
|
uses 24 bits with `första` in the upper 8 bits and `andra`
|
|
in the lower 16.
|
|
|
|
```hs
|
|
data Maybe a = Nothing | Just
|
|
```
|
|
|
|
a will use $1+n$ bits,
|
|
where $n$ bits are needed to represent values of type `a`. The extra bit
|
|
will be the most significant bit and it will be 0 (followed by $n$
|
|
unspecified bits) for `Nothing` and 1 (followed by the $n$ bits for `a`)
|
|
for `Just`.
|
|
|
|
|
|
### Deriving `Eq`
|
|
|
|
|
|
The instances derived for the `Eq` class is the natural equality for the
|
|
type. For a struct all fields have to be equal, for a data type the
|
|
constructors have to be equal and then all their parts.
|
|
|
|
|
|
### Deriving `Bounded`
|
|
|
|
|
|
An instance for `Bounded` can be derived for an enumeration type,
|
|
*i.e.,* a data type where all constructors are niladic. The `minBound`
|
|
will be the first constructor and the `maxBound` will be the last.
|
|
|
|
`Bounded` can also be derived for a `struct` type if all the field types
|
|
of the struct are `Bounded`. The `minBound` will be the struct with all
|
|
fields having their respective `minBound`, and correspondingly for
|
|
`maxBound`.
|
|
|
|
### Deriving for isomorphic types
|
|
|
|
A data type with one constructor and one argument is isomorphic to its
|
|
type argument. For such a type any one-parameter class can be used, in a
|
|
`deriving`, for which there is an instance for the underlying type.
|
|
|
|
Example:
|
|
|
|
```hs
|
|
data Apples = Apple (UInt 32) deriving (Literal, Arith)
|
|
five :: Apples
|
|
five = 5
|
|
eatApple :: Apples -\> Apples
|
|
eatApple n = n - 1
|
|
```
|