Haskell 中数据类型的笛卡尔积

Cartesian product of data types in Haskell

正在尝试将两种数据类型的笛卡尔积放入列表中:

 data X = hello | goodbye | hi 
      deriving (ord, enum, eq, show)
 data Y = hello | goodbye | hi 
      deriving (ord, enum, eq, show)

 compList :: [a]
 compList = [(x, y) | x <- X, y <- Y]

显然 x <- X 等目前不起作用,我只是想知道你们会怎么做?

干杯。

除了大小写问题和这里不能有两个同名的数据构造函数之外,我认为最简单的方法是包含 Bounded 然后你就差不多明白了:

data X = Hello | Goodbye | Hi 
      deriving (Enum, Bounded, Show)

data Y = Hello2 | Goodbye2 | Hi2
       deriving (Enum, Bounded, Show)

compList :: [(X,Y)]
compList = [(x, y) | x <- [minBound..maxBound], y <- [minBound..maxBound]]

使用 Enum 你可以使用 [a .. b] 语法(你可能已经知道)并且 Bounded 给你 minBoundmaxBound


产出

λ> compList
[(Hello,Hello2),(Hello,Goodbye2),(Hello,Hi2),(Goodbye,Hello2),(Goodbye,Goodbye2),(Goodbye,Hi2),(Hi,Hello2),(Hi,Goodbye2),(Hi,Hi2)]

当然如果你不想使用Bounded你可以自己给限制:

data X = Hello | Goodbye | Hi 
      deriving (Enum, Show)

data Y = Hello2 | Goodbye2 | Hi2
       deriving (Enum, Show)

compList :: [(X,Y)]
compList = [(x, y) | x <- [Hello .. Hi], y <- [Hello2 .. Hi2]]

当然这里几乎和说 [Hello,Goodbye,Hi] 一样长 ;)

可以派生Enum和Bounded。这允许你写:

data X = hello | goodbye | hi
  deriving (Show, Enum, Bounded)

data Y = a | b | c
   deriving (Show, Enum, Bounded)

allX :: [X]
allX = [minBound..maxBound]

allY :: [Y]
allY = [minBound..maxBound]

allXY = [ (x,y) | x <- allX, y <- allY ]