Haskell数据类型范围

时间:2018-04-12 21:31:09

标签: haskell types

我定义了自己的数据类型。

data Row = A | B | C deriving (Show,Eq,Ord)

问题是,如果有更优雅的方式来定义我的范围而不是这个?

instance Ix Row where
  range (A,A) = [A]
  range (A,B) = [A,B]
  range (A,C) = [A,B,C]
  range (B,B) = [B]
  range (B,C) = [B,C]
  range (C,C) = [C]
  range _     = []

2 个答案:

答案 0 :(得分:12)

有:导出Enum并定义

range (x, y) = [x .. y]

答案 1 :(得分:10)

使用Enum实例

是的,您可以Row {strong} Enum 的实例,事实上您不必自己定义:

data Row = A | B | C deriving (Show, Eq, Ord, Enum)

这意味着我们现在可以使用“范围表示法”。例如:

Prelude> [A .. C]
[A,B,C]
Prelude> [A .. B]
[A,B]
Prelude> [C .. B]
[]

因此,我们现在可以将Ix实例定义为:

instance Ix Row where
    range (x, z) = [x .. z]
    index (x, _) y = fromEnum y - fromEnum x
    inRange (x, z) y = x <= y && y <= z

甚至没有参数:

instance Ix Row where
    range = uncurry enumFromTo
    -- ...

通过定义自定义“后继”功能

如果你不想让它成为Enum实例(我在这里看不到任何理由,但这当然是一个相当假设的数据类型)。我们可以使用递归和每次计算后继来构造一个列表:

instance Ix Row where
    range (x, z) = go x
        where go y | y > z = []
              go A = A : go B
              go B = B : go C
              go C = [C]

虽然上面的代码片段仍然是大量工作,但它会将线性与数据构造函数的数量进行比较,而详尽的方法则会将 quadratic 与数据构造函数的数量(的时间复杂度,但代码量)。