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