bluespec-docs/content/chapter4/page6.md

114 lines
3.9 KiB
Markdown
Raw Normal View History

2025-02-12 20:54:12 +00:00
+++
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
```