[Haskell-cafe] Existential type question
Daniel Fischer
daniel.is.fischer at web.de
Sun Nov 22 13:59:58 EST 2009
Am Sonntag 22 November 2009 19:24:48 schrieb Michael Snoyman:
> Hi all,
>
> I've come across some code I just can't figure out how to write
> appropriately. Below is a silly example that demonstrates what I'm trying
> to do. I don't really have the appropriate vocabulary to describe the
> issue, so I'll let the code speak for itself. In particular, I'm trying to
> understand what the correct type signatures for unwrapMyData and bin should
> be.
>
> Thanks,
> Michael
>
> ---
>
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# LANGUAGE ExistentialQuantification #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE FlexibleContexts #-}
> class Monad m => MonadFoo x m where
> foo :: x -> m a
>
> data MyData a = forall i. Integral i => MyLeft i
>
> | MyRight a
>
> instance Monad MyData where
> return = MyRight
> (MyLeft i) >>= _ = MyLeft i
> (MyRight x) >>= f = f x
> instance Integral i => MonadFoo i MyData where
> foo = MyLeft
>
> bar :: MonadFoo Int m => Int -> m String
> bar 0 = return "zero"
> bar i = foo i
>
> baz :: String -> MyData String
> baz "zero" = MyRight "Zero"
> baz _ = MyLeft (-1 :: Integer)
>
> --This works: unwrapMyData (MyLeft i) = foo (fromIntegral i :: Integer)
> unwrapMyData (MyLeft i) = foo i -- This is what I'd like to work
I don't see how it could (except perhaps...). The type would be
unwrapMyData ::(forall i. (Integral i => MonadFoo i m)) => MyData a -> m a
- the MyData a -> m a part is obviously necessary, but MyLeft can wrap *any* integral
type, so you indeed need instances MonadFoo i m for *every* integral type. You can't
specify that condition in Haskell.
You could try
instance MonadFoo a [] where
foo _ = []
instance MonadFoo a Maybe where
foo _ = Nothing
(more general,
instance (MonadPlus m) => MonadFoo a m where
foo _ = mzero
)
unwrapMyData :: (MonadPlus m) => MyData a -> m a
that might be got to work, but it's very likely not even remotely what you want
(unwrapMyData :: MyData a -> [a] would work with the above instance, I think, but it would
be rather pointless).
> unwrapMyData (MyRight a) = return a
>
> bin i = do
> a <- bar i
You must specify which instance of MonadFoo to use here, otherwise it is impossible to
determine which instance of bar to use, and the type of bin is irredeemably ambiguous
(show . read).
> b <- unwrapMyData $ baz a
> return $ b ++ "!!!"
>
> instance Show a => MonadFoo a IO where
> foo = fail . show -- I know, it's horrible...
>
> main = do
> res <- bin 0
> putStrLn res
More information about the Haskell-Cafe
mailing list