help on writing a typeclass
I got a function, named mdk (don't ask). It happens it's a method of a class, as follows: class C a where mdk :: C b => a -> b -> (a, b) yet i got another function, called so far mdk' mdk' :: C b => b -> a -> (a, b) Say there are the following instances: instance C X where mdk x b = ... :: C b => (X, b) mdk' b x = ... :: C b => (X, b) instance C Y where mdk y b = ... :: C b => (Y, b) mdk' b y = ... :: C b => (Y, b) if you get what's happening, mdk and mdk' are basically the same method, save for the final type-result, which is reversed, without data loss mind you (aka (A, B) and (B, A) could be the same type, if only i knew of a way to make a type in haskell without forcing the order (a kind of set or something). so, there are four cases: input have types, in this order, X and Y, and expected output is (X, Y): then mdk from X's instance of C is called/must be used; input have types Y and X, output (X, Y): X's mdk' input X and Y, output (Y, X): Y's mdk input Y and X, output (Y, X): Y's mdk' it might seem confusing, but all amounts to the issue that even though (Y, X) is strictly equivalent, in my program, to (X, Y), in principle haskell differentiate the types. thus i have to write two versions of mdk for each type, even though the methods "X's mdk" and "Y's mdk'" are identical, and same for the two other methods. indeed: mdk :: C b => X -> b -> (X, b) mdk' :: C b => b -> Y -> (Y, b) are identical signatures, if in the first one you replace `b` with Y, and in the latter you replace `b` with X, and ofc if you consider (X,Y) == (Y,X). only one of those two methods should be enough to handle the job, and be chosen by the compiler on the sole value of the type of the first variable; but the fact both methods return tuples of "mirrored" types, crushes that. if i only write `mdk` instances, as soon as the compiler will meet this following signature: mdk :: a -> b -> (b, a) it will crash an exception, because mdk's original signature has for output value a tuple whose first type should here be `a`, because it's meant to be the type of the first argument, not the second. thus, at last my question: can i tell the compiler to consider (b, a) and (a, b) as identical types (don't worry it's not really a tuple in my program, but it's equivalent)? if not, can i make an overloading of mdk so it accepts both a->b->(a,b) and a->b->(b,a)? hope i didn't lose anyone. if so, do tell me, i'll try to clarify. thanks in advance of the time spent trying to understand my problem!
Got an idea, is it the right path? Are there bad consequences in using the extensions that are necessaries to make the code work? class Mdk binary a | binary -> a where mdk :: a -> b -> binary instance Mdk (a,b) a where mdk = ... :: a -> b -> (a,b) instance Mdk (b, a) a where mdk = ... :: a -> b -> (b, a) then, however, even if it works, mdk will never be part of the other class i was working on, and at that point i'm a bit lost on the consequences of this... Le samedi 4 juin 2016, Silent Leaf <silent.leaf0@gmail.com> a écrit :
I got a function, named mdk (don't ask). It happens it's a method of a class, as follows:
class C a where mdk :: C b => a -> b -> (a, b)
yet i got another function, called so far mdk' mdk' :: C b => b -> a -> (a, b)
Say there are the following instances: instance C X where mdk x b = ... :: C b => (X, b) mdk' b x = ... :: C b => (X, b) instance C Y where mdk y b = ... :: C b => (Y, b) mdk' b y = ... :: C b => (Y, b)
if you get what's happening, mdk and mdk' are basically the same method, save for the final type-result, which is reversed, without data loss mind you (aka (A, B) and (B, A) could be the same type, if only i knew of a way to make a type in haskell without forcing the order (a kind of set or something). so, there are four cases: input have types, in this order, X and Y, and expected output is (X, Y): then mdk from X's instance of C is called/must be used; input have types Y and X, output (X, Y): X's mdk' input X and Y, output (Y, X): Y's mdk input Y and X, output (Y, X): Y's mdk'
it might seem confusing, but all amounts to the issue that even though (Y, X) is strictly equivalent, in my program, to (X, Y), in principle haskell differentiate the types. thus i have to write two versions of mdk for each type, even though the methods "X's mdk" and "Y's mdk'" are identical, and same for the two other methods. indeed: mdk :: C b => X -> b -> (X, b) mdk' :: C b => b -> Y -> (Y, b) are identical signatures, if in the first one you replace `b` with Y, and in the latter you replace `b` with X, and ofc if you consider (X,Y) == (Y,X).
only one of those two methods should be enough to handle the job, and be chosen by the compiler on the sole value of the type of the first variable; but the fact both methods return tuples of "mirrored" types, crushes that. if i only write `mdk` instances, as soon as the compiler will meet this following signature: mdk :: a -> b -> (b, a) it will crash an exception, because mdk's original signature has for output value a tuple whose first type should here be `a`, because it's meant to be the type of the first argument, not the second.
thus, at last my question: can i tell the compiler to consider (b, a) and (a, b) as identical types (don't worry it's not really a tuple in my program, but it's equivalent)? if not, can i make an overloading of mdk so it accepts both a->b->(a,b) and a->b->(b,a)?
hope i didn't lose anyone. if so, do tell me, i'll try to clarify.
thanks in advance of the time spent trying to understand my problem!
would this work: {-# LANGUAGE MultiParamTypeClasses, InstanceSigs #-} module Mdk where data C a b = Ab a b | Ba b a class Mdk a b where mdk::a -> b -> C a b instance (Eq a, Eq b) => Eq (C a b) where (==)::C a b -> C a b -> Bool (==) (Ab a1 b1) (Ab a2 b2) = a1 == a2 && b1 == b2 (==) (Ab a1 b1) (Ba b2 a2) = a1 == a2 && b1 == b2 (==) (Ba b2 a2) (Ab a1 b1) = a1 == a2 && b1 == b2 (==) (Ba b2 a2) (Ba b1 a1) = a1 == a2 && b1 == b2 ?
participants (2)
-
Imants Cekusins -
Silent Leaf