Question

Is it possible to use case expression between two unrelated types in Haskell, like in this example (not working) code:

data A = A
data B = B

f x = case x of
  A -> 1
  B -> 2

main = do
  print $ test A
  return ()

I know I can use Either here, but this code is not meant to be used - I want to deeply learn the Haskell type system and see what could be done.

Was it helpful?

Solution

A and B are distinct types. If you want a function that can take values of multiple types, you need a typeclass.

data A = A
data B = B

class F a where
  f :: a -> Int

instance F A where
  f _ = 1

instance F B where
  f _ = 2

main = do
  print $ f A

OTHER TIPS

No, this is not possible with a normal case statement, but you can hack this sort of thing using type classes:

data A = A
data B = B

class Test a where
    test :: a -> Int

instance Test A where test = const 1
instance Test B where test = const 2

main = print $ test A

But you should only use this if it's really required, as it gets messy very soon and you end up with needing a lots of extensions to the type system (UndecidableInstances, OverlappingInstances, ...)

Rather than writing your own type class for f, you could use the Typeable class which has some support by ghc. You don't need to use Dynamic here, but in some cases it is needed.

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Dynamic

data A = A deriving (Typeable)
data B = B deriving (Typeable)

f x | Just A <- fromDynamic x = 1
    | Just B <- fromDynamic x = 2

f2 x | Just A <- cast x = 1
     | Just B <- cast x = 2

main = do
  print $ f (toDyn A)
  print $ f2 A
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top