
Em Qui, 2009-04-09 às 01:55 +0200, Daniel Fischer escreveu:
Am Donnerstag 09 April 2009 00:29:24 schrieb Marco Túlio Gontijo e Silva:
Hello,
I'm getting this error message from GHC in the following code:
type M a = Monad m => m a
class A a b where f :: Monad m => a -> m b
instance A String Char where f string = return $ head string
instance A Char Int where f int = return $ fromEnum int
I thought at first to write h like this, but it gives me the error. If I write it like the other h uncommented, there's no error. I can't see why they aren't equivalent.
h :: IO () h = f "abc" >>= (f :: Char -> M Int) >>= print
h :: IO () h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ())
---------------------------------------------------------------- class B a b where foo :: a -> M b
instance B String Char where foo str = return $ head str
instance B Char Int where foo c = return $ fromEnum c
k :: IO () k = foo "abc" >>= (foo :: Char -> M Int) >>= print ----------------------------------------------------------------
works, as does
m = foo "abc" >>= (foo :: Char -> (forall x. Monad x => x Int)) >>= print
And that reveals what's going on, since m is in fact the same as k. The type of f in class A says that given any specific monad m and a value of type a, f can produce a value of type m b. But when you write (f :: Char -> M Int) , you say that given a Char, f produces a value which belongs to m Int *for every monad m*. Thus the type you state for f (the expected type) is more polymorphic than the actual type f has according to the class definition (which is the inferred type).
Ok, I got it, so I tried changing class A in my example to:
class A a b where f :: forall m . Monad m => a -> m b
so that the type of f would be as polymorphic as the type a -> M b. But I got the same problem. Your solution is good, but I can't do it in my real application where I find out this problem, because the type synonym M is defined after the class A, and it contains more than on type constraint:
type Interpret value = ( MonadReader Input monad , MonadState Machine monad , MonadWriter Stream monad) => monad value
My use is that I have some classes defined in modules included by the one that defines type Interpret, like this:
class Value pointer value where getValue :: (MonadReader Program monad, MonadState Machine monad) => pointer -> monad value
And even if they were defined in the same file, it would not be good to define them as Interpret, because it would restrict its type. Another thing: I understand your explanation, but I don't get why this makes the other h definition valid. Could you clarify me on that? Thanks. -- marcot http://marcot.iaaeee.org/