我定义了自己的数据类型。
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 _ = []
答案 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 与数据构造函数的数量(不的时间复杂度,但代码量)。