f# - 如何约束类型参数必须是代数类型(int、float、BigInteger、BigRational、...)
问题描述
- 虽然网上有一些问题。类型约束已经,我没有找到可以帮助我解决问题的约束。--
目标:我想创建自己的 Vector/Matrix 类型,但是,实现不会锁定到特定的 BigRational(或类似)类型。我更喜欢要求的是对此类类型的标准代数运算(+ - * / % 相等)。
open System
type Foo<'T> (value: 'T) =
member inline __.Value : 'T = value
static member inline Add (a: Foo<'T>) (b: Foo<'T>) =
Foo<'T>(a.Value + b.Value)
module Foo =
let inline Create (v) = Foo(v)
let log (foo: #Foo<_>) =
printfn "Foo: %s" (foo.Value.ToString())
[<EntryPoint>]
let main argv =
Foo.log (Foo.Create("hi ho"))
Foo.log (Foo<int>(31415))
Foo.log (Foo<float>(3.1415))
Foo.log (Foo<int>.Add (Foo.Create(3)) (Foo.Create(4)))
let a = Foo.Create(13)
let b = Foo.Create(3.1415)
Foo.log (Foo<int>.Add (a.Value) (a.Value))
Foo.log (Foo<float>.Add (b.Value) (b.Value))
0 // return an integer exit code
我无法让这个微小的示例代码为多个单一类型编译,Foo<int>
例如Foo<float>
. 我怎么能做对?
非常感谢,克里斯蒂安。
解决方案
实际上,您几乎拥有它。
为了创建一个接受具有+
运算符的任何类型的函数,该函数必须具有静态解析类型参数(SRTP)。为此,它必须是内联的,这是你Add
的,所以没关系。但是这里Add
不是泛型方法:它是泛型类型上的方法Foo<'T>
,因此它'T
从它接收参数。并且一个类型不能有 SRTP。
一个简单的解决Add
方法是将类型上的方法Foo<'T>
转变为模块中的函数Foo
。然后它将变得实际上是通用的。
open System
type Foo<'T> (value: 'T) =
member inline __.Value : 'T = value
module Foo =
let inline Create (v) = Foo(v)
let inline Add (a: Foo< ^T>) (b: Foo< ^T>) =
Foo< ^T>(a.Value + b.Value)
let log (foo: #Foo<_>) =
printfn "Foo: %s" (foo.Value.ToString())
[<EntryPoint>]
let main argv =
Foo.log (Foo.Create("hi ho"))
Foo.log (Foo<int>(31415))
Foo.log (Foo<float>(3.1415))
Foo.log (Foo.Add (Foo.Create(3)) (Foo.Create(4)))
let a = Foo.Create(13)
let b = Foo.Create(3.1415)
Foo.log (Foo.Add a a)
Foo.log (Foo.Add b b)
0
推荐阅读
- javascript - 使用传单地理搜索添加搜索栏
- android - 更改屏幕锁定回调
- google-cloud-platform - Google Cloud Shell Editor 未加载资源
- azure - 为什么 Azure 函数不写入服务总线主题
- android - Mapbox fitbounds 选项仅适用于 Android,适用于 IOS
- php - PHP 中的 while 和 file_exists
- mysql - 四张表的mysql查询错误
- javascript - 如何从 Firebase 数据库中的对象获取数据?
- python - Python - ETree element.find 部分匹配
- android - 使用 LiveData 依赖项构建时“无法解决:support-fragment”