经常有人想要<=>
在产品数据类型上实现(比较,或“宇宙飞船”)运算符,即具有多个字段的类(所有这些(我们希望!)已经<=>
实现),比较某个字段中的字段命令。
def <=>(o)
f1 < o.f1 && (return -1)
f1 > o.f1 && (return 1)
f2 < o.f2 && (return -1)
f2 > o.f2 && (return 1)
return 0
end
这既乏味又容易出错,尤其是对于很多领域。它很容易出错,以至于我经常觉得我应该对该函数进行单元测试,这只会增加乏味和冗长。
Haskell 提供了一种特别好的方法:
导入 Data.Monoid (mappend) 导入 Data.Ord(比较) -- 来自标准库: -- 数据排序 = LT | 情商 | 燃气轮机 数据 D = D { f3 :: Int, f2 :: Double, f1 :: Char } 推导 Show compareD :: D -> D -> 排序 compareD = foldl1 mappend [比较 f1,比较 f2,比较 f3]
(对于那些不熟悉的人fold
,以上扩展为
comparing f1 `mappend` comparing f2 `mappend` comparing f3
它产生一个可应用于两个D
s 的函数,以产生一个Ordering
.)
的定义compareD
非常简单,显然是正确的,即使没有静态类型检查,我也不觉得需要对其进行单元测试。
实际上,这个问题可能比这更有趣,因为我可能不想只使用标准<=>
运算符,而是在不同的时间以不同的方式排序,例如:
sortByOrderings :: [a -> a -> 排序] -> [a] -> [a] sortByOrderings = sortBy 。foldl1 映射 sortByF3F1 = sortByOrderings [比较 f3,比较 f1] sortByF2F3 = sortByOrderings [比较 f2,比较 f3]
所以,问题:
- 在 Ruby 中实现这类事情的典型方法是什么?
- 仅使用标准库中定义的内容最好的方法是什么?
- 相比之下,与上面的 Haskell 代码有多接近,它的可靠性如何?如有必要,如何确保字段具有正确实施的
<=>
or<
和>
运算符?
顺便说一句,虽然这是一个 Ruby 问题,但如果该站点的长辈们同意,我很高兴考虑讨论有关 Haskell 技术的主题。请随时评论这是否合适,如果合适,请将此帖子标记为“haskell”。