[clean-list] Question about uniqueness type error

Jeremy Shaw jeremy.shaw@lindows.com
Sun, 02 Nov 2003 13:51:59 -0800


Hello,

I am getting a uniqueness error I can not explain when I try to
combine type synonyms and classes. I can't figure out if I am
misunderstanding something, or if it is a compiler bug.

The following code is based on some actually code I wrote, but with
all the irrelevant stuff stripped out for readability.

----->

module test

import StdEnv

:: MonoFrames a  :== .{#a}
:: StereoFrames a :== .(.{#a},.{#a})

:: Stream a 	= MonoStream .(MonoFrames a)
		| StereoStream .(StereoFrames a)

class Frames a where
    mixInFrames :: *a *a -> *a

instance Frames (MonoFrames *Int) where
    mixInFrames :: *(MonoFrames *Int) *(MonoFrames *Int) -> *(MonoFrames *Int)
    mixInFrames frames1 frames2 = frames2

// This variation does not work
instance Frames (StereoFrames *Int) where
    mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int)
    mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r)

/*
// This one works
instance Frames (*{#*Int},*{#*Int}) where
    mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int})
    mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r)
*/

// so does this 
mixInFrames2 :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int)
mixInFrames2 (f1l, f1r) (f2l, f2r) = (f2l, f2r)


mixInStream :: *(Stream *Int) *(Stream *Int) -> *(Stream *Int)
mixInStream (MonoStream frames1)   (MonoStream frames2)   = (MonoStream   (mixInFrames frames1 frames2))
mixInStream (StereoStream frames1) (StereoStream frames2) = (StereoStream (mixInFrames frames1 frames2))

Start = "Hello, World!"

<-----

If I try to compile the code as shown, I get the following error:

clm test -o test
Compiling test
Uniqueness error [test.icl,36,mixInStream]:"argument 1 of StereoStream" attribute at indicated position could not be coerced *(^ {#*Int},{#*Int})
Uniqueness error [test.icl,36,mixInStream]:"argument 2 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int)
Uniqueness error [test.icl,36,mixInStream]:"argument 1 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int)
make: *** [test] Error 1

If I comment out this instance:
instance Frames (StereoFrames *Int)

And uncomment this instance:
instance Frames (*{#*Int},*{#*Int})

The code compiles without any errors. OR, if I change mixInStream to
call mixInFrames2, it also compiles fine.

So I am confused. 

How come mixInFrames2 works, but the 'instance Frames
(StereoFrames *Int)' gives a uniqueness error.
 
Am I correct in thinking that:

mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int)

is a type synonym for:

mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int})

Thanks.
Jeremy Shaw.

ps. I tested this with clean 2.1 for linux.