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.

有帮助吗?

解决方案

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

其他提示

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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top