Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Either be used for a kind of simple polymorphism?

Tags:

haskell

I tried writing a simple function that takes an Either type (possibly parameterized by two different types) and does one thing if it gets Left and another thing if it gets Right. the following code,

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

main = do
  someFunc (Left "Test1")
  someFunc (Right "Test2")

However, this gives,

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 the function with Left x, it is complaining because it doesn't know the type of the Right x variant, and vice-versa. However, this branch of the function is not used. Is there a better way to do this?

like image 618
Steve Avatar asked Dec 16 '22 05:12

Steve


1 Answers

You can make this work by explicitly specifying the other type:

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

but I agree with x13n that this probably isn't the best way to do whatever you're trying to do. Note that someFunc is functionally identical to

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 derive from the structure of the Either is whether it's a Left or Right. This version also doesn't require you to specify a placeholder type when you use it.

like image 51
ehird Avatar answered Feb 16 '23 00:02

ehird