可区分联合的运算符重载 [英] Operator overloading for discriminated union

查看:77
本文介绍了可区分联合的运算符重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一些可以处理标量或向量的数字代码(在这种情况下,分别是来自 DiffSharp 的 D 和 DV 类型).有时我希望能够使用任何一个,所以我为它们定义了一个可区分的联合:

I'm trying to write some numerical code that can work with either scalars or vectors (in this case it's the D and DV types respectively, from DiffSharp). Sometimes I want to be able to use either so I've defined a discriminated union for them:

type IBroadcastable =
    | Scalar of D
    | Vect of DV

对于这两种类型已经有很多运算符重载了,所以为了在 IBroadcastable 上使用它们,我编写了这样的添加代码到联合中:

A lot of operators are already overloaded for both of these types, so to use them on IBroadcastable I write add code like this to the union:

static member Exp x = 
    match x with
        | Scalar x -> Scalar (exp x)
        | Vect x -> Vect (exp x)

这看起来很多余.有什么方法可以在联合上使用运算符而不必为其编写新的重载?或者我应该使用不同的模式(即不是歧视工会)?我想将这种类型用于的示例:

This seems very redundant. Is there any way I can use the operator on the union without having to write a new overload for it? Or I should I be using a different pattern (i.e. not a discriminated union)? An example of what I want to use this type for:

let ll (y: IBroadcastable) (theta: IBroadcastable) = y*theta-(exp theta)

*- 将有更复杂的行为(数组广播),必须描述自己是有道理的,但 exp 运算符很简单,如上所述.这需要是一个函数,因为我希望能够部分应用 y 参数,使用 DiffSharp 获得梯度,并相对于 theta 参数最大化它.

The * and - will have more complicated behaviour (array broadcasting), which it makes sense to have to describe myself, but the exp operator is simple, as above. This needs to be a function since I want to be able to partially apply the y argument, get the gradient with DiffSharp, and maximise it with respect to the theta argument.

推荐答案

你的示例函数 ll 实际上更通用——它可以处理任何支持它使用的操作的东西,甚至是那些不是 DDV.如果您使用 inline 定义它,那么您将能够在两者上调用该函数:

Your sample function ll is actually even more generic - it can work on anything that supports the operations it uses, even things that are not D or DV. If you define it using inline, then you will be able to call the function on both:

let inline ll y theta = y*theta-(exp theta)

inline 修饰符允许 F# 使用静态成员约束,在调用函数时,所需成员可以满足这些约束(与必须使用 .NET 运行时提供的内容编译的普通泛型函数不同).

The inline modifier lets F# use static member constraints, which can be satisfied by the required members when calling the function (unlike with normal generic functions that have to be compiled using what .NET runtime provides).

我希望这不适用于您的所有代码,因为您将需要一些特定于 DDV 的操作,但没有通用的 F# 函数,例如作为 exp.您实际上可以使用静态成员约束访问那些,尽管这有点麻烦.

I expect this will not work for all your code, because you will need some operations that are specific to D and DV, but do not have generic F# function such as exp. You can actually access those using static member constraints, though this gets a bit hairy.

假设 DDV 值都有一个成员 Foo 返回 string,你可以写:>

Assuming D and DV values both have a member Foo returning string, you can write:

let inline foo (x:^T) = 
  (^T : (member Foo : string) x)

let inline ll y theta = y*theta-(exp theta)+foo y

这篇关于可区分联合的运算符重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆