Can a simple polymorphism be used for a kind?

I tried to write a simple function that takes any type (possibly parameterized by two different types) and does one if it gets Left and the other if it becomes correct. following code

someFunc :: (Show a, Show b) => Either ab -> IO () someFunc (Left x) = print $ "Left " ++ show x someFunc (Right x) = print $ "Right " ++ show x main = do someFunc (Left "Test1") someFunc (Right "Test2") 

However, it does,

 Ambiguous type variable `b0' in the constraint: (Show b0) arising from a use of `someFunc' Probable fix: add a type signature that fixes these type variable(s) In a stmt of a 'do' expression: someFunc (Left "Test1") 

and

 Ambiguous type variable `a0' in the constraint: (Show a0) arising from a use of `someFunc' Probable fix: add a type signature that fixes these type variable(s) In the expression: someFunc (Right "Test2") 

If I understand correctly, when I call a function using Left x , it complains because it does not know the type of the Right x variant and vice versa. However, this function branch is not used. Is there a better way to do this?

+4
source share
3 answers

Well, that depends a lot on what you are trying to do, right? As you can see, to use the Left constructor you need to know the type that it creates. And the full type requires information on both a and b .

The best way to achieve polymorphism in Haskell is to use type classes. You can easily provide different implementations of the "methods" for different instances.

A good comparison of object class concepts and class types can be found here .

+3
source

You can do this work by explicitly specifying a different type:

 main = do someFunc (Left "Test1" :: Either String ()) someFunc (Right "Test2" :: Either () String) 

but I agree with x13n that this is probably not the best way to do what you are trying to do. Note that someFunc functionally identical

 someFunc :: (Show a) => Bool -> a -> IO () someFunc False x = print $ "Left " ++ show x someFunc True x = print $ "Right " ++ show x 

because the only information you get from the Either structure is that it is Left or Right . This version also does not require specifying the type of placeholder when using it.

+5
source

This is a good question because it made me think about why Haskell behaves this way.

 class PseudoArbitrary a where arb :: a instance PseudoArbitrary Int where arb = 4 instance PseudoArbitrary Char where arb = 'd' instance PseudoArbitrary Bool where arb = True reallyDumbFunc :: (PseudoArbitrary a, PseudoArbitrary b) => Either ab -> Either ab reallyDumbFunc (Left x) = Right arb reallyDumbFunc (Right x) = Left arb 

So check this out. I made a typeclass PseudoArbitrary where typeclass instances provide a (pseudo) arbitrary element of their type. Now I have a reallyDumbFunc that takes Either ab , where both a and b have PseudoArbitrary instances, and if a Left was entered, I create a Right , with a (pseudo) arbitrary value of type b in it and vice versa. So now let's play ghci:

 ghci> reallyDumbFunc (Left 'z') Ambiguous type variable blah blah blah ghci> reallyDumbFunc (Left 'z' :: Either Char Char) Right 'd' ghci> reallyDumbFunc (Left 'z' :: Either Char Int) Right 4 

Wow! Despite the fact that everything I changed was an input type, it completely changed the type and value of the output! This is why Haskell cannot solve this ambiguity on its own: because it will require a complex analysis of your function to make sure that you are not doing things like reallyDumbFunc .

+5
source

Source: https://habr.com/ru/post/1390886/


All Articles