
Colleagues! The essence of trouble may be given by code: [haskell] module TypeTrouble where class FirstClass a where firstFunction :: (SecondClass b) => a -> b class SecondClass a where secondFunction :: a -> Double data FirstData = FirstData Double data SecondData = SecondData Double instance SecondClass SecondData where secondFunction (SecondData d) = d instance FirstClass FirstData where firstFunction (FirstData d) = SecondData d [/haskell] I need, the firstFunction of FirstClass types to return a value of a SecondClass type. For example SecondData for FirstData, but for some FirstClass ThirdData, some SecondClass FourthData, etc. GHC 6.8.1 produces an error: [quote] typetrouble.hs:17:31: Couldn't match expected type `b' against inferred type `SecondData' `b' is a rigid type variable bound by the type signature for `firstFunction' at typetrouble.hs:4:31 In the expression: SecondData d In the definition of `firstFunction': firstFunction (FirstData d) = SecondData d In the definition for method `firstFunction' [/quote] How can I make this idea work? -- With best regards, Konstantin

On Tue, Dec 25, 2007 at 08:11:34AM +0300, Konstantin Vladimirov wrote:
[haskell] module TypeTrouble where
class FirstClass a where firstFunction :: (SecondClass b) => a -> b
class SecondClass a where secondFunction :: a -> Double [/haskell]
I need, the firstFunction of FirstClass types to return a value of a SecondClass type. For example SecondData for FirstData, but for some FirstClass ThirdData, some SecondClass FourthData, etc.
The problem, as is often the case, is that that which is unwritten does not resolve in the way you expect and require it to. FirstClass' true signature is class FirstClass a where firstFunction :: a -> forall b. SecondClass b => b That is to say, any implementation of firstFunction must work for ANY instance of SecondClass. But you want SOME, not ANY. And SOME (normally notated exists tvar. tspec) is not supported in any known dialect of Haskell. It's possible to get fairly close with GHC Haskell's fundeps / type families: -- fundep version class SecondClass b => FirstClass a b where firstFunction :: a -> b -- type family version class SecondClass (Cod a) => FirstClass a where type Cod a :: * firstFunction :: a -> Cod a It is almost certainly possible to accomplish your goals within standard Haskell, but the best approach is not obvious at the current level of detail. Stefan

On Dec 25, 2007 12:11 AM, Konstantin Vladimirov
class FirstClass a where firstFunction :: (SecondClass b) => a -> b
instance FirstClass FirstData where firstFunction (FirstData d) = SecondData d
The problem is that the type of firstFunction as producing a result of type 'b', where 'b' is *any* type inahbiting the typeclass "SecondClass." Your definition of firstFunction can produce only *one* of the inhabitants of "SecondClass". You'd think this would be okay, seeing as there is only one member of the typeclass, but because anyone can come along and add a new typeclass instance, you're definition of "firstFunction" needs to account for that. If you're type-classes only ever have one instance, maybe it's easier to not use them, and go with:
convert :: FirstData -> SecondData convert (FirstData d) = SecondData d
But I'm not sure if that suggestion is at all helpful. -Antoine

Hi Konstantin, Here is yet another possible approach: Perhaps you really meant what you wrote in your definition of firstFunction - namely, that it needs to be polymorphic, so that it can convert to _any_ type that is an instance of SecondClass. In that case, you might want to add another method to SecondClass: class SecondClass a where secondConstructor :: Double -> a secondFunction :: a -> Double instance SecondClass SecondData where secondConstructor = SecondData secondFunction (SecondData d) = d Now you can say: instance FirstClass FirstData where firstFunction (FirstData d) = secondConstructor d In short, it all depends on what exactly you are trying to do. Hope this helps, Yitz

Hello Konstantin, Tuesday, December 25, 2007, 8:11:34 AM, you wrote:
class FirstClass a where firstFunction :: (SecondClass b) => a -> b
this looks like one more attempt to use OOP thinking in Haskell. look at http://haskell.org/haskellwiki/OOP_vs_type_classes and especially papers referenced there -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (5)
-
Antoine Latter
-
Bulat Ziganshin
-
Konstantin Vladimirov
-
Stefan O'Rear
-
Yitzchak Gale