Problem
|
Für Typsynonyme sind keine neuen instance
Deklarationen möglich
|
| |
Beispiel
|
type Cartesian = (Float, Float)
type Polar = (Float, Float)
type Angle = Float
|
|
2 unterschiedliche Darstellungen für komplexe Zahlen
|
| |
|
Operationen unterschiedlich: +, -, *, /, ==, /=,
... bei Cartesian und Polar
|
|
bei Angle: ==, /=, ... anders als in Float realisiert
|
| |
Lösung
|
data Angle = MkAngle Float
instance Eq Angle where
MkAngle x == MkAngle y = normalize x == normalize y
normalize :: Float -> Float
normalize x
| x < 0 = normalize (x + rot)
| x >= rot = normalize (x - rot)
| otherwise = x
where
rot = 2 * pi
|
| |
|
Alle Werte werden mit dem Konstrukor MkAngle "eingewickelt"
|
| |
|
Laufzeiteffizienz: "Einwickeln" und "Auswickeln" kosten Platz und Zeit
|
| |
|
Neuer Wert
|
|
|
| |
|
Angle ist nicht isomorph zu Float
|
| |
Lösung
|
newtype Angle = MkAngle Float
|
| |
|
Der Konstruktor MkAngle ist strikt |
|
|
| |
|
Angle und Float sind isomorph
|
| |
|
Laufzeiteffizienz: "Einwickeln" und "Auswickeln" kann im Compiler eliminiert werden,
also entsteht keine Laufzeitverschlechterung.
|
| |
|
Für mit newtype deklarierte Typen sind wie für data neuen instance
Deklarationen möglich.
|
| |
|
Ein sehr teurer Fehler durch Mischen von Größen unterschiedlicher physikalischer Einheiten:
Mars Climate Orbiter disaster
|