我正在尝试编写一些可以与标量或向量一起使用的数字代码(在这种情况下,分别是来自 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/

10-12 21:22