我正在尝试编写一些可以与标量或向量一起使用的数字代码(在这种情况下,分别是来自 DiffSharp 的 D 和 DV 类型)。有时我希望能够使用它们,所以我为它们定义了一个可区分的联合:
type IBroadcastable =
| Scalar of D
| Vect of DV
许多运算符已经为这两种类型重载,所以为了在
IBroadcastable
上使用它们,我编写了这样的代码到联合:static member Exp x =
match x with
| Scalar x -> Scalar (exp x)
| Vect x -> Vect (exp x)
这似乎非常多余。有什么方法可以在联合上使用运算符而不必为其编写新的重载?或者我应该使用不同的模式(即不是歧视工会)?我想将此类型用于的示例:
let ll (y: IBroadcastable) (theta: IBroadcastable) = y*theta-(exp theta)
*
和 -
会有更复杂的行为(数组广播),这个我自己描述一下是有道理的,但是 exp
操作符很简单,如上。这需要是一个函数,因为我希望能够部分应用 y 参数,使用 DiffSharp 获得梯度,并相对于 theta 参数最大化它。 最佳答案
从根本上说,由于您正在定义一个抽象,因此您需要根据该抽象来定义您的操作。这是一个成本,它必须通过它在代码中的其他地方为您提供的便利来抵消。
您可能想知道 F# 是否会让您在特定情况下削减样板。除了使用 function
关键字之外,并不是真的,因为两个分支实际上在做不同的事情:绑定(bind)变量 x
的类型不同,并且您将它们包装在不同的联合案例中。如果你真的在做同样的事情,你可以这样写,例如:
type DU =
| A of float * float
| B of float * string
with
static member Exp = function
| A (b, _)
| B (b, _) -> exp b // only write the logic once
关于f# - 可区分联合的运算符重载,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44170378/