Clean class declarations
Marko van Eekelen
marko@cs.kun.nl
Thu, 26 Jun 1997 14:54:25 +0200
Dear Alan,
>Anyone who can suggest solutions to the following conundrums will earn
>thanks and blessings.
I will go for that.
>Below is some Clean code (.icl) which is meant to define generic metrics
>on various data types. The instances on types Int and Real compile
>without errors. All the others fail.
>
>The metrics on tuples seem to fail because the class contexts restrict
>more than one type variable, so they violate the 10th semantic rule
>(see the Concurrent Clean 1.1 Language Report section 8.4.11, page 59).
This was not the problem: the type you gave for the function d was just too restrictive.
The restriction refers to the number of class variables of the class definition:
>class Metric a | == a
>where
> d :: !a !a -> Real
has just one class variable a. (the restriction to one class variable will probably be alleviated in the next version of Clean).
>The metric on (finite!) lists seems to violate the 4th rule.
Same problem: too restrictive type definition of d.
BTW: the types for d at this point are optional: the line beginning with instance actually already spcifies the type of the function. So the following would have been ok too.
instance Metric (a,b) | Metric a & Metric b
where
d (t,u) (v,w) = d t v + d u w
instance Metric (a,b,c) | Metric a & Metric b & Metric c
where
d (t,u,x) (v,w,y) = d t v + d u w + d x y
>I do not understand why the default rule does not compile.
>What is a "class variable"?
See the example above. it is the variable you can instantiate:
e.g.:
class Metric a | == a
where
d :: !a !a -> Real
instance Metric (a,b) | Metric a & Metric b
where
d (t,u) (v,w) = d t v + d u w
a is instantiated with (a,b) | Metric a & Metric b yielding as the type for d:
d :: !(a,b) !(a,b) -> Real | Metric a & Metric b
>With thanks for any comments.
My pleasure.
>Alan Hutchinson
>Department of Computer Science
>King's College London
Marko van Eekelen.
Nijmegen University.
P.S. The following compiles without problems in Clean version 1.2.3.
-------------------------------------------------------------------------
implementation module metrics
import StdEnv//, hausdorf
// the function hausdorf should be of type: hausdorff:: (![a] ![a] -> Real) ![a] ![a] -> Real | Metric a
// just a dummy definition inserted here
hausdorff:: (![a] ![a] -> Real) ![a] ![a] -> Real | Metric a
hausdorff d xs ys = 0.0
Start = Start
class Metric a | == a
where
d :: !a !a -> Real
instance == a default
where
(==) infix 4 :: !a !a -> Bool
(==) x y = False
instance Metric Int
where
d :: !Int !Int -> Real
d x y = toReal (abs (x-y))
instance Metric Real
where
d :: !Real !Real -> Real
d x y = abs (x-y)
instance Metric (a,b) | Metric a & Metric b
where
d :: !(a,b) !(a,b) -> Real | Metric a & Metric b
d (t,u) (v,w) = d t v + d u w
instance Metric (a,b,c) | Metric a & Metric b & Metric c
where
d :: !(a,b,c) !(a,b,c) -> Real | Metric a & Metric b & Metric c
d (t,u,x) (v,w,y) = d t v + d u w + d x y
instance Metric [a] | Metric a
where
d :: ![a] ![a] -> Real | Metric a
d xs ys = hausdorff d xs ys
instance Metric a default
where
d :: !a !a -> Real
d x y
| x == y = 0.0
| otherwise = 1.0