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.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to