| Expected behavior: Expected the type class to be accepted.
| This example was posted to comp.lang.functional by Sigbjorn Finne
| on March 30, as an example of how Haskell multi-parameter type classes
| would be used.  I had tried something similar earlier the same day,
| without success.  So I tried the posted example, and got the same
| kind of failure.

I didn't see the comp.lang.functional posting, but it isn't a good
example of how multiple parameter classes should be used.

| ERROR "bug1.hs" (line 5): Ambiguous type signature in class declaration
| *** ambiguous type : Stream a b => a c -> c -> IO ()
| *** assigned to    : write
| 
| ...
|
| class Stream source sink where
|    makeStream :: Priority -> (source a, sink a)
|    write      :: source a -> a -> IO ()
|    read       :: sink a -> IO a
|    pipe       :: source a -> sink a -> IO ()     -- never returns

In this case at least, Hugs is right.  The Haskell type system does not
allow the use of functions with ambiguous principal types.  (A type of
the form P => t is ambiguous if there is a variable in P that does not
also appear in t.)  This restriction is needed to guarantee that
programs have a well-defined semantics; it is sometimes referred to as
a coherence property.  Even from a practical perspective, there is
little point in allowing terms with ambiguous principal types because
there will never be any way for such uses of overloading to be
resolved.

The class definition that you gave defines two functions with ambiguous
types:

 write :: Stream src sink => src a -> a -> IO ()  -- doesn't mention sink
 read  :: Stream src sink => sink a -> IO a       -- doesn't mention src

And that is why Hugs (correctly) rejects this program.  To solve this,
you might consider restructuring your class hierarchy along the following
lines:

  class (RStream sink, WStream src) => Stream src sink where
    makeStream :: Priority -> (src a, sink a)
    pipe       :: src a -> sink a -> IO ()

  class RStream sink where
    read       :: sink a -> IO a       -- doesn't mention src

  class WStream src where
    write      :: src a -> a -> IO ()  -- doesn't mention sink

I hope this helps!

All the best,
Mark

Reply via email to