Question related to Multi Param Type Classes

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Question related to Multi Param Type Classes

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)


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


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Question related to Multi Param Type Classes

Bulat Ziganshin-2
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:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Question related to Multi Param Type Classes

Bugzilla from alfonso.acosta@gmail.com
In reply to this post by Sai Hemanth K
2008/5/5 Sai Hemanth K <[hidden email]>:
> 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.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Question related to Multi Param Type Classes

Brandon S Allbery KF8NH
In reply to this post by Sai Hemanth K

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] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Question related to Multi Param Type Classes

Ryan Ingram
On 5/5/08, Brandon S. Allbery KF8NH <[hidden email]> wrote:
> 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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe