[Haskell-cafe] Problem with result-type context restrictions
in typeclasses.
Miguel Mitrofanov
miguelimo38 at yandex.ru
Wed Sep 30 03:00:22 EDT 2009
> class Cls c where
> type Ret c :: (Bar *) => * -- or a better name
> foo :: c -> Ret c
>
> which isn't legal Haskell.
OK, that's exactly the same thing I've met when developing
compose-trans. I needed guarantees that something is a Monad.
My way of doing that was to make "Bar" ("Monad" in my case) a datatype.
Suppose you "Bar" class is something like
class Bar c where
toBar :: String -> c
changeBar :: c -> Int -> c
fromBar :: c -> c -> [Float]
Declare something like
data BarD c =
BarD
{toBarD :: String -> c,
changeBarD :: c -> Int -> c,
fromBarD :: c -> c -> [Float]}
I've did it some other way, using the Monad specifics, but essentially
it was the same.
Then you can write a default "BarD" this way:
barDInst :: Bar c => BarD c
barDInst =
BarD
{toBarD = toBar,
changeBarD = changeBar,
fromBarD = fromBar}
Do not (!) export BarD constructor, so the only BarD one would be able
to produce would be the default one. It simplifies you interface.
Now, your "Cls" looks like that:
class Cls c where
type Ret c
barRet :: BarD (Ret c)
foo :: c -> Ret c
If somebody is using your class, she can't be sure that "Ret c" is of
class "Bar", but she would have sort of an instance anyway: she would
just use "toBarD barRet" instead of "toBar", and so on. If somebody is
trying to make some "c" an instance of "Cls" - the only thing she can do
is to make some "d" an instance of "Bar" and write
instance Cls MyCoolInstance where
type Ret MyCoolInstance = MyCoolRetType
barRet = barDInst
foo c = ...
It's higly possible, however, that you'd have to deal with "Ambiguous
type variable"'s.
More information about the Haskell-Cafe
mailing list