Question related to Multi Param Type Classes

Hi, I declared a multi param type class as below: *class MyString m c where zIndex :: m -> Int -> c zLength :: m -> Int zPack :: [c] -> m zEquals :: c ->c -> Bool zWrap :: [c] -> (m,AnExistingDataType)* In the end I did not needed it for my program, but for those few minutes I played with the idea, I came across a zillion questions. Can some body help me here please? When I defined a function like below, \begin{code} compareStr::(MyString m c) => (m,Int) ->(m,Int)->Int->Int compareStr (s1,pos1) (s2,pos2) soFar | (pos1 < zLength s1) && (pos2 < zLength s2) = let c1 = zIndex s1 pos1 c2 = zIndex s2 pos2 in if(zEquals c1 c2) then compareStr (s1,(pos1 + 1)) (s2, (pos2 + 1)) (soFar + 1) else soFar | otherwise = soFar \end{code} when I loaded it on ghci ( invoked with -XMultiParamTypeClasses ), I got an essay in greek (or is it latin?), which started something like below: Could not deduce (MyString m c) from the context (MyString m c4) arising from a use of `zLength' at GenericZAlgo.lhs:42:21-31 Possible fix: add (MyString m c) to the context of the type signature for `compareStr' In the second argument of `(<)', namely `zLength s1' In the first argument of `(&&)', namely `(pos1 < zLength s1)' In a pattern guard for the definition of `compareStr': (pos1 < zLength s1) && (pos2 < zLength s2) And if I let the type inference run the show, the type it shows is : compareStr :: (MyString t c2, MyString m c2, Num a, MyString t1 c2, MyString t c, MyString t1 c1) => (t, Int) -> (t1, Int) -> a -> a And puzzlingly, if I try the same thing myself and reload it on the ghci,I still get similar error. I can go on about other 'puzzles'. Can some one please tell me whats going on here? Apologies, if it is something that's been documented left to right, top to bottom, but I could not get anywhere readily. Any pointers to the right documentation will be much appreciated. On the surface it looks like something that n00bs like yours truly better stay away. But I have a feeling that this one may throw some more light on type inference. Many thanks

Hello Sai, Monday, May 5, 2008, 7:52:29 PM, you wrote:
class MyString m c where
it should be class MyString m c | m->c where so ghc will realize that same m means the same c. read about "functional dependencies" in ghc user manual -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

2008/5/5 Sai Hemanth K
Hi,
I declared a multi param type class as below: class MyString m c where zIndex :: m -> Int -> c zLength :: m -> Int zPack :: [c] -> m zEquals :: c ->c -> Bool zWrap :: [c] -> (m,AnExistingDataType)
I infer from your questions that you probably missed setting a functional dependency, that is
class MyString m c | m -> c where zIndex :: m -> Int -> c zLength :: m -> Int zPack :: [c] -> m zEquals :: c ->c -> Bool zWrap :: [c] -> (m,AnExistingDataType)
which means, "c is univocaly determined by m". You'll need -XFunctionalDependencies to make it work in GHC.

On May 5, 2008, at 11:52 , Sai Hemanth K wrote:
when I loaded it on ghci ( invoked with -XMultiParamTypeClasses ), I got an essay in greek (or is it latin?), which started something like below: Could not deduce (MyString m c) from the context (MyString m c4) arising from a use of `zLength' at GenericZAlgo.lhs:42:21-31
Other people gave you the "how"; here's the why. The problem is that, with the information available to ghc from your definitions, there is no way to fix a type for "c". It can't use the instances it knows about because type classes are open; that is, someone could add another instance in a different source file (or even later in the existing one) and suddenly "c" would not be determinable. This is considered a bad thing. What this means in practice is that when GHC tries to type "compareStr", because "c" is never used in the function, it can fix "m" but it can't fix "MyString m c". Therefore it can't prove that the same "MyString m c" applies to both arguments that refer to "m" --- which is what that error quoted above means. The functional dependency "MyString m c | m -> c" tells GHC that any specific "m" determines a specific "c". It doesn't matter what the type is here, since it's not used in the definition of compareStr; but it must be possible to know that the same "c" is being used in both arguments. Given this, it can fix "MyString m c" knowing only "m" and as a result the function typechecks. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On 5/5/08, Brandon S. Allbery KF8NH
The functional dependency "MyString m c | m -> c" tells GHC that any specific "m" determines a specific "c". It doesn't matter what the type is here, since it's not used in the definition of compareStr; but it must be possible to know that the same "c" is being used in both arguments. Given this, it can fix "MyString m c" knowing only "m" and as a result the function typechecks.
Although this still makes it impossible to call zEquals for the same reason; you need a dependency in both directions for it to make sense. -- ryan
participants (5)
-
Alfonso Acosta
-
Brandon S. Allbery KF8NH
-
Bulat Ziganshin
-
Ryan Ingram
-
Sai Hemanth K