Hello, I've been playing around with GTK+HS recently. This makes extensive use of Haskell classes, so I sometimes get strange type errors like this one.. textNew (creates a new text widget) has type: textNew :: AdjustmentClass adj => Maybe adj -> Maybe adj -> IO Text But when I try to create one using: txt <- textNew Nothing Nothing GHC complains: Main.hs:82: Ambiguous type variable(s) `a' in the constraint `GtkAdjustment.AdjustmentClass a' arising from use of `textNew' at Main.hs:82 in a `do' expression pattern binding: txt <- textNew Nothing Nothing My first thought was that I need a type signature for txt, but seeing as txt has to be type IO Text, I dont think that's possible (because 'adj' is not referenced). Is that correct? So, what should one do in this situation? Something like this perhaps.. myNothing :: Maybe dummyAdjustmentClassInstance myNothing = Nothing txt <- textNew myNothing myNothing I'm pretty sure that would do it, but it seems like an ugly solution. Is there a better way? Thanks -- Adrian Hey
Hello, Adrian wrote:
textNew (creates a new text widget) has type: textNew :: AdjustmentClass adj => Maybe adj -> Maybe adj -> IO Text
But when I try to create one using: txt <- textNew Nothing Nothing
GHC complains: Main.hs:82: Ambiguous type variable(s) `a' in the constraint `GtkAdjustment.AdjustmentClass a' arising from use of `textNew' at Main.hs:82 in a `do' expression pattern binding: txt <- textNew Nothing Nothing
My first thought was that I need a type signature for txt, but seeing as txt has to be type IO Text, I dont think that's possible (because 'adj' is not referenced). Is that correct?
The problem is that GHC can not find out (From the two Nothing objects) which instance of AdjustmentClass to use. Different instances might lead to different "IO Text" objects, so choosing a default is impossible. For example: show ([] :: [Int]) == "[]" and show ([] :: [Char]) == "\"\"" Therefore, you have to tell GHC the exact type of "textNew Nothing Nothing" with a type annotation, just like in the examples with show above: txt <- textNew (Nothing :: Maybe SomeDefaultAdjustmentClass) Nothing In this case, supplying the type of one of the two Nothing values is enough (GHC can find out the other one must be the same).
So, what should one do in this situation? Something like this perhaps.. myNothing :: Maybe dummyAdjustmentClassInstance myNothing = Nothing txt <- textNew myNothing myNothing I'm pretty sure that would do it, but it seems like an ugly solution. Is there a better way?
This is indeed one solution. This way, you tell GHC a dummy instance is possible; unlike the show-situation where it is impossible). Using type annotations is another solution, but it is not as comfortable if you are supplying textNew often with just twice Nothing. If it's just a few cases, I prefer this option. As a last alternative, only useful if you use "textNew Nothing Nothing" often, is to write a special function for this case (in all other cases, GHC can infer the right type so we don't need a special function): textNewNothing = textNew (Nothing :: Maybe SomeDefaultAdjustmentClass) Nothing Regards, Rijk-Jan
On Friday 02 November 2001 4:46 pm, Rijk-Jan van Haaften wrote:
Therefore, you have to tell GHC the exact type of "textNew Nothing Nothing" with a type annotation, just like in the examples with show above:
txt <- textNew (Nothing :: Maybe SomeDefaultAdjustmentClass) Nothing
Ah yes, I'd forgotten you could do that these days. This still lacks elegance IMHO, but it's not quite as bad as what I proposed. Thinking about this, it occurs to me that maybe this kind of ambiguity could be safely ignored by the compiler if the following constraint was enforced... Functions can only make use of class methods if they have been given a genuine class member in an argument. The compiler could check this quite easily I think. Either the function does pattern matching on the argument, or it passes the argument (and method table) on to another function which is similarly constrained. Either way it's safe. So in situations like this the compiler could use some suitable dummy method table with confidence, knowing it would never be used. Would this be possible? I suppose if the methods include functions which don't take a class member as an argument (or constants) this could cause problems. Just an idea. I don't think this would help with your show example though, which as you observed, is ambiguous for a different reason. Regards -- Adrian Hey
participants (2)
-
Adrian Hey -
Rijk-Jan van Haaften