单一案件歧视联盟的目的

yam*_*men 13 monads f# discriminated-union

我正在定义一个monadic observable/reactive解析器.这与普通解析器的行为完全不同,因为它是连续查询.基础类型是:

IObservable<'a> -> IObservable<'b>
Run Code Online (Sandbox Code Playgroud)

通过查看函数式语言中的各种解析器实现,似乎更合适的定义事物的方式是单个案例区分联合:

type Pattern<'a,'b> = Pattern of (IObservable<'a> -> IObservable<'b>)
Run Code Online (Sandbox Code Playgroud)

这意味着我需要提取底层函数来使用它:

let find (Pattern p) = p
Run Code Online (Sandbox Code Playgroud)

问题是:这只是按惯例,还是为了以后扩展的目的,或者即使定义永远不会改变,是否有理由这样做?

奖金问题:如果只是为了更方便的类型签名,为什么不使用类型别名:

type Pattern<'a,'b> = IObservable<'a> -> IObservable<'b>
Run Code Online (Sandbox Code Playgroud)

我已经通过这种方式取得了很大的进步,并且没有找到不使用DU来影响可组合性的情况.

pad*_*pad 15

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)
Run Code Online (Sandbox Code Playgroud)

但它不会像使用DUs那样提供透明度:

type Vector = V of float * float

// val add : Vector -> Vector -> Vector
let add (V(x1, y1)) (V(x2, y2)) = V(x1 + y1, x2 + y2)
Run Code Online (Sandbox Code Playgroud)

在复杂的程序中,清晰类型签名确实可以更容易地保持可组合性.

不仅可以更简单地向单个案例的DU添加更多案例,而且使用成员和静态方法扩展DU也更容易.一个例子是你经常覆盖ToString()漂亮的打印.

  • 一个后续的许多月亮。我的确给联盟增加了第二个案例,因此宇宙处于平衡状态。 (2认同)