Haskell自定义Row类型:更优雅的Ix实例range实现方案问询
更优雅的Ix range实现方式
当然有!你当前的写法虽然能正确工作,但需要手动枚举所有可能的区间组合,不仅代码冗余,而且如果以后扩展Row类型(比如新增一个D构造器),还得手动添加一堆新的case,维护成本很高。
利用Enum类型类简化实现
你的Row是一个典型的枚举类型,而且已经派生了Eq和Ord(这是Ix类型类的必要约束),我们可以借助Enum类型类的能力来自动生成区间元素。
首先给Row派生Enum:
data Row = A | B | C deriving (Show, Eq, Ord, Enum)
然后我们可以用fromEnum和toEnum来转换元素与整数,进而生成区间:
instance Ix Row where range (start, end) | start > end = [] -- 处理起始大于结束的无效区间 | otherwise = map toEnum [fromEnum start .. fromEnum end]
这个实现的逻辑很清晰:
- 先判断区间是否有效(起始元素大于结束时返回空列表,符合
Ix的规范) - 把
Row元素转成对应的整数(Haskell枚举类型默认从0开始编号:A→0,B→1,C→2) - 生成从起始整数到结束整数的连续序列
- 再把每个整数转回
Row类型,得到完整的区间列表
终极优雅:直接派生Ix
如果你的Row只需要遵循Ix类型类的标准行为,甚至可以直接让GHC自动为你生成所有Ix方法(包括range),只需要启用DeriveIx扩展:
{-# LANGUAGE DeriveIx #-} data Row = A | B | C deriving (Show, Eq, Ord, Enum, Ix)
这样连instance Ix Row都不用写了!GHC会自动生成符合规范的range、index、inRange等方法,扩展性拉满——以后新增Row的构造器时,完全不需要修改任何额外代码。
内容的提问来源于stack exchange,提问作者Ben373
相关产品推荐
相关产品推荐

