F# 如何约束类型参数必须是代数类型(int、float、BigInteger、BigRational等)

F# 如何约束类型参数必须是代数类型(int、float、BigInteger、BigRational等),f#,F#,--虽然网上有一些问题。类型约束已经存在,我没有找到一个可以帮助我解决问题的约束-- 目标:我想创建自己的向量/矩阵类型,但这样,实现就不会锁定到特定的BigRational(或类似)类型。我更愿意要求的是对此类类型的标准代数运算(+-*/%相等) 开放系统 输入Foo)(b:Foo(a.Value+b.Value) 模块Foo= 让内联创建(v)=Foo(v) 让日志(foo:#foo)= printfn“Foo:%s”(Foo.Value.ToString()) [] 让主argv= Foo

--虽然网上有一些问题。类型约束已经存在,我没有找到一个可以帮助我解决问题的约束--

目标:我想创建自己的向量/矩阵类型,但这样,实现就不会锁定到特定的BigRational(或类似)类型。我更愿意要求的是对此类类型的标准代数运算(+-*/%相等)

开放系统
输入Foo)(b:Foo(a.Value+b.Value)
模块Foo=
让内联创建(v)=Foo(v)
让日志(foo:#foo)=
printfn“Foo:%s”(Foo.Value.ToString())
[]
让主argv=
Foo.log(Foo.Create(“hi-ho”))
Foo.log(Foo(31415))
Foo.log(Foo(3.1415))
Foo.log(Foo.Add(Foo.Create(3))(Foo.Create(4)))
设a=Foo.Create(13)
设b=Foo.Create(3.1415)
Foo.log(Foo.Add(a.Value)(a.Value))
Foo.log(Foo.Add(b.Value)(b.Value))
0//返回整数退出代码
我无法让这个小示例代码为多个单一类型进行编译,例如
Foo
以及
Foo
。我如何才能正确地进行编译

多谢各位,
克里斯汀。

事实上,你几乎拥有了它

为了创建一个函数来接受任何具有
+
运算符的类型,此函数必须具有(SRTP)。为此,它必须是内联的,您的
Add
就是内联的。但是这里的
Add
不是泛型方法:它是泛型
Foo(值:'T)上的方法=
成员内联值:'T=Value
模块Foo=
让内联创建(v)=Foo(v)
让内联添加(a:Foo<^T>)(b:Foo<^T>)=
Foo<^T>(a.Value+b.Value)
让日志(foo:#foo)=
printfn“Foo:%s”(Foo.Value.ToString())
[]
让主argv=
Foo.log(Foo.Create(“hi-ho”))
Foo.log(Foo(31415))
Foo.log(Foo(3.1415))
Foo.log(Foo.Add(Foo.Create(3))(Foo.Create(4)))
设a=Foo.Create(13)
设b=Foo.Create(3.1415)
Foo.log(Foo.adda)
Foo.log(Foo.Add b)
0

如果您只想传播F#重载算术运算符的成员约束,那么您所需要的只是关键字

type Foo<'T> (value : 'T) =
    member __.Value = value
    static member inline (+) (a : Foo<_>, b : Foo<_>) = Foo(a.Value + b.Value)
    // static member
    //   ( + ) : a:Foo< ^a> * b:Foo< ^b> -> Foo< ^c>
    //             when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)
键入Foo*b:Foo<^b>->Foo<^c>
//当(^a或^b):(静态成员(+):^a*^b->^c)

现在,您可以添加两个相同类型的
Foo
,它们支持静态成员
(+)
foo3+foo4
foo3.14+foo3.14
,甚至
Foo(foo3)+Foo(foo4)
;但不是
foo3+foo3.14
。您仍然可以实例化不具有此类成员的类型。

Hey@Tarmil,非常感谢您的回答。我尝试了您的解决方案(通过将copn'y'放入我的测试项目中),它抱怨以下错误:Program.fs(9,16):错误FS1113:值'Add'被内联标记,但它的实现使用了一个内部或私有函数,该函数不可充分访问(..对于
value
..,也是如此)。遗憾的是,它没有告诉我为什么它“不可充分访问”。最后,我想实现(+),等等。
type Foo<'T> (value : 'T) =
    member __.Value = value
    static member inline (+) (a : Foo<_>, b : Foo<_>) = Foo(a.Value + b.Value)
    // static member
    //   ( + ) : a:Foo< ^a> * b:Foo< ^b> -> Foo< ^c>
    //             when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)