Clean class declarations

Alan Hutchinson alanh@dcs.kcl.ac.uk
Wed, 25 Jun 1997 19:12:49 +0100 (BST)


Anyone who can suggest solutions to the following conundrums will earn
thanks and blessings.

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).

The metric on (finite!) lists seems to violate the 4th rule.

I do not understand why the default rule does not compile.
What is a "class variable"?

This code was tested with Clean1.1 under Linux.
If these problems are solved in a later version, please excuse me.

With thanks for any comments.
Alan Hutchinson
Department of Computer Science
King's College London

--------------------------------------------------------------------------

implementation module metrics

import StdEnv, hausdorf

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
//   d (t,u) (v,w)  =  d t v + d u w
                                  // NOTE This context restricts two type
                                  // variables, so may not work (sect. 8.4.11)

// instance Metric (a,b,c) | Metric a & Metric b & Metric c
// where
//   d :: !(a,b,c) !(a,b,c) -> Real
//   d (t,u,x) (v,w,y)  =  d t v + d u w + d x y
                                   // NOTE restricts three type
                                   // variables, so may not work.

// instance Metric [a]  | Metric a //  NOTE [a] is not a FLAT TYPE (sect. 8.4.11)
// where                           //       so this may not work.
//   d :: ![a] ![a] -> Real
//   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

// Type error [metrics.icl,48,d (default)]:
// specified type is too general (class variable expected)