Spire 有一个 Interval 类型,可以做你想做的事情。
附录
关于您关于创建Interval 实例的更简洁语法的问题。有几个选项。一种是简单地使用 import 使创建过程不那么冗长:
import Interval.{closed => ci}
val ci1 = ci(1.0, 2.0)
……但这并没有太大的改进。
另一种选择可能是使用从 Tuple2[Double, Doublle] 到 Interval[Double] 的隐式转换:
implicit def t2toI(pair: Tuple2[Doube, Double]): Interval[Double] =
Interval.closed(pair._1, pair._2)
val ci2: Interval[Double] = (1.0, 2.0)
在这种情况下,必须给出 val 的类型使得这又是一个收益不大的情况。但是,如果您正在调用一个以Interval[Double] 作为参数的方法,则该方法的形式参数的类型注释足以触发隐式转换。
我实际上对 Spire 了解不多,但如果只有一个 Interval 某种内部状态反映了开放端点和封闭端点之间的差异,那么您的问题是只有一个从 Tupel2[Double, Double] 到 @987654331 的隐式转换@ 可以在范围内,因此您无法控制创建其他三种开放和封闭端点组合中的任何一种。实际上,现在我想起来了,Spire 如何表示区间并不重要,除非隐式转换的输入包含有关要创建哪种区间的信息,否则问题就成立了。我想,您可以向元组添加更多插槽以区分端点打开/关闭。再一次,你失去了一些简洁性,它从来没有像使用数学文本的符号那样优雅。
因为括号和方括号都“属于”语言规范,传统的数学符号将永远无法用于经典的内部 DSL。
最后,可能是最好的解决方案,您可以创建一个字符串插值器,使您能够编写如下内容:
val i1 = i"[1.0, $end)"
val i2 = i"($begin, 4.0]'
等等。同样,我还没有任何直接经验,但我相信用于创建新插值器的 API 非常简单。