Algebraic types and subclassing

Arjan van IJzendoorn arjanij@cs.kun.nl
Thu, 12 Mar 1998 10:34:08 +0100


Hi Nick,

>The difference is that:
>
>Add :: Int Int -> Int
>Add = (+)
>
>Doesn't work, although I think it ought to.

Why not write "Add :: (Int -> Int -> Int); Add = (+)" ?
Then the type doesn't look so nice, but the definition does.

>>>- Language level support for ADTs. Data hiding is pretty tricky without
>>>this. And you *can't* hide types without this.
>>
>>It is possible to hide types using the module structure of Clean (exporting
>the type >constructor, but not its definition.
>
>The idea is to not allow the programmer to construct types himself. RGB
>1092348 1024980918 24096834 is obviously invalid. If you had an ADT, your
>makeRGB function could throw exceptions with such parameters. The idea is to
>prevent  these sort of things from being even possible.
>(Note that this example could be satisfied by my proposed class
>"assertions:"

Again, this can be done by using Clean's module system:

--------------
definition module RGB

:: RGB		// Note: the implementation is not revealed

makeRGB :: Int Int Int -> RGB	// The "constructor"

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

implementation module RGB

import StdEnv

:: RGB = { red :: Int, green :: Int, blue :: Int }

makeRGB :: Int Int Int -> RGB
makeRGB red green blue
  | all (between 0 255) [red, green, blue]
    = { red = red, green = green, blue = blue }
  | otherwise
    = abort "makeRGB (RGB.icl): illegal arguments"

between :: Int Int Int -> Bool
between lower upper value
  = value >= lower && value <= upper

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

Now, users of the module RGB can only construct RGB values using
the constructor.

Bye,
  Arjan