Haskell数据类型范围

Ben*_*373 4 haskell types

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

data Row = A | B | C deriving (Show,Eq,Ord)
Run Code Online (Sandbox Code Playgroud)

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

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 _     = []
Run Code Online (Sandbox Code Playgroud)

mel*_*ene 12

有:推导Enum和定义

range (x, y) = [x .. y]
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 10

通过使用Enum实例

是的,您可以创建Row一个实例Enum,实际上您不必自己定义它:

data Row = A | B | C deriving (Show, Eq, Ord, Enum)
Run Code Online (Sandbox Code Playgroud)

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

Prelude> [A .. C]
[A,B,C]
Prelude> [A .. B]
[A,B]
Prelude> [C .. B]
[]
Run Code Online (Sandbox Code Playgroud)

所以我们现在可以将我们的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
Run Code Online (Sandbox Code Playgroud)

甚至没有参数:

instance Ix Row where
    range = uncurry enumFromTo
    -- ...
Run Code Online (Sandbox Code Playgroud)

通过定义自定义"后继"功能

如果你不想让它成为一个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]
Run Code Online (Sandbox Code Playgroud)

虽然上面的代码片段仍然是一个大量的工作,它缩放线性与数据构造的数目,而详尽的方法中,将缩放二次用数据构造的数目(在时间复杂度,但在代码量) .