toString, aka overloading problems

Sjaak Smetsers sjakie@cs.kun.nl
Thu, 4 Jun 1998 09:49:48 +0100


>The problem I have is attempting to convert various structures to string
>representations for printout.
>
>
>Here's each piece I can't figure out. I've changed the problem from String
>to something else so multiple abstract types don't get in the way.
>
>---
>Part 1
>
>Implementations:
>	class test a :: a -> [Int]
>
>	// Pretend these instances do something useful
>	instance test [Int]
>		where
>		test a = (map ((+) 1) a)
>
>	instance test [[Int]]
>		where
>			test a = (map sum a)		// <--- line 67
>
>Generates
>	Error [test.icl,67,test ([])]: test ([]) multiply defined symbol
>
>If the instances are alternately commented out, the derived types are
>respectively:
>	test ([]) :: ![Int] -> [Int];
>	test ([]) :: ![[Int]] -> [Int];
>
>If the second instance is commented out, and I try:
>	bobo = test [[1]]		// <-- line 69
>
>I get the error:
>	Type error [test.icl,69,bobo]: "argument 1 of test" cannot unify
>demanded type [[Int]] with [Int]
>Which is kinda what I hoped for.
>
>Since the types are distinct, [[]] vs [], I think I should be able to have
>instances of them.

There are technical reasons to forbid this. Instance types should be
distinguishable on the basis of the outermost type constructor, in this
case List. Hence the two instances are considered to be overlapping, and
therefore not allowed.

>The compiler prevents me from evaluating the wrong type,
>and it derives the two types, yet seems to get it wrong in instances.
>

I don't understand what you mean.

>Is there a way to do this:
>	define a function a -> b
>		such that
>			if 'a' is not a list f' is applied,
>			if 'a' is a list, f'' (function a) is applied,
>			where
>				f' converts 'a' to 'b'
>				f'' converts [b] to 'b'
>	so arguments of the various types 'x', [x], [[x]], [[[x]]], etc,
>will work?

If you cannot use the standard overloading mechanism  (which means that you
should be able to specify all list versions in a single instance for lists)
such a function is impossible (as far as I know).

>Part 2
>
>For the implementation:
>
>	:: BitString = BitString	// pretend this is a useful type
>
>	class test a :: a -> BitString
>
>	// pretend these instances do some useful conversion
>	instance test [a] | toInt a
>		where test x = BitString
>	instance test [a] | toReal a
>		where test x = BitString	// <-- line 78
>
>I get the error:
>	Error [test.icl,78,test ([])]: test ([]) multiply defined symbol
>
>I thought that the instances where analogous to partial functions, and I
>could just specify more. Apparently not.
>
>Is there a way to do this (use fn A if toReal works, use fn B if toInt works)?
>

This is forbidden for the same reason as mentioned in part 1.

Sjaak Smetsers