
On Mon, Oct 22, 2007 at 08:02:20PM +0200, Henrik Tramberend wrote:
Dear Hasekellers,
I am trying to build some abstractions on top of the module Control.Concurrent and run into a problem with the type system that I do not understand.
In particular, I want to define two classes 'Channel' and 'Port' (see below) that define a common interface for several concrete implementations with different synchronization characteristics.
The following code is a simplified excerpt that demonstrates the problem:
module Main where import Control.Concurrent.MVar
class Channel c where port :: Port p => c a -> IO (p a)
This type signature means that 'port' is return type overloaded - it can return ANY kind of port, and the caller gets to choose. Which I don't think is what you want. A possible solution is to hide the nature of the port, and use a record of functions: data Port a = Port { put :: a -> IO (), get :: IO a } class Channel c where port :: c a -> Port a Another possible approach, if it is vital for clients to know the nature of the port: class Port (PortOf c) => Channel c where type PortOf c :: * -> * port :: c a -> PortOf c a class Port p where get :: p a -> IO a put :: p a -> a -> IO () (Requires type family extension in GHC 6.8; an equivalent formulation using the older (2000) functional dependancies is possible) Stefan