我正在定义一个单子可观察/反应式解析器。这与普通解析器的行为完全不同,因为它是连续查询。底层类型是:
IObservable<'a> -> IObservable<'b>
从函数式语言中的各种解析器实现来看,似乎定义事物的更合适的方法是单例区分联合:
type Pattern<'a,'b> = Pattern of (IObservable<'a> -> IObservable<'b>)
这意味着我需要提取底层函数才能使用它:
let find (Pattern p) = p
问题是:这只是按照惯例,还是为了以后扩展的目的,或者即使定义从未改变,是否有理由这样做?
额外问题:如果只是为了更方便的类型签名,为什么不直接使用类型别名:
type Pattern<'a,'b> = IObservable<'a> -> IObservable<'b>
我已经在这方面取得了很大进展,并且还没有发现不使用 DU 会影响可组合性的情况。
F# 编译器不保留有关类型缩写的信息,因此您无法从中受益类型推断根本不。类型签名可以理解为程序规范;让类型检查器完成其工作是确保程序正确性的好方法。
在类型别名的情况下,您需要在任何地方显式指定类型注释:
type Vector = float * float
// val add : float * float -> float * float -> Vector
let add ((x1, y1): Vector) ((x2, y2): Vector): Vector = (x1 + y1, x2 + y2)
但它并没有为您提供使用 DU 时的透明度:
type Vector = V of float * float
// val add : Vector -> Vector -> Vector
let add (V(x1, y1)) (V(x2, y2)) = V(x1 + y1, x2 + y2)
在复杂的程序中,清晰的类型签名确实可以更轻松地维护可组合性。
不仅可以更简单地向单例 DU 添加更多案例,而且可以更轻松地使用成员和静态方法扩展 DU。一个例子是你经常覆盖ToString()
为了漂亮的打印。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)