Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/251.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 是否可以编写通用函数<’;T>;其中‘;T被约束为类型为';T2*';T3?_Generics_F# - Fatal编程技术网

Generics 是否可以编写通用函数<’;T>;其中‘;T被约束为类型为';T2*';T3?

Generics 是否可以编写通用函数<’;T>;其中‘;T被约束为类型为';T2*';T3?,generics,f#,Generics,F#,在F#中是否可以编写一个泛型函数,其中指定类型“T”,但将“T”约束为类型“T2*”T3的元组 以下是我尝试过的几个只会产生编译器错误的方法: let fun1<'T when 'T :> 'T2*'T3> () = … let fun2<'T, 'T2, 'T3 when 'T :> 'T2*'T3> () = … 让fun1'T2*'T3>()=… 让fun2'T2*'T3>()=… (在fun2中,'T2/'T3最好由'T1推断。) 我之所以要这样做

在F#中是否可以编写一个泛型函数,其中指定类型“T”,但将“T”约束为类型“T2*”T3的元组

以下是我尝试过的几个只会产生编译器错误的方法:

let fun1<'T when 'T :> 'T2*'T3> () = …
let fun2<'T, 'T2, 'T3 when 'T :> 'T2*'T3> () = …
让fun1'T2*'T3>()=…
让fun2'T2*'T3>()=…
(在fun2中,'T2/'T3最好由'T1推断。)

我之所以要这样做,是因为我正在使用内存中的数据库编写一个应用程序,并且我正在尝试编写一个通用函数,该函数以指定的元组形式提取与数据库实体关联的数据。我有一个可行的解决方案,但有几个缺点:

let workingExtractEntity<'T> (id : EntityID) (db: Database) : EntityID*'T =
        let t = db.GetEntityComponent id typeof<'T>
        (id, t)
让workingExtractEntity
(id、t2、t3)
类型Player=EntityID*位置*运行状况
让extractPlayer id db:Player=extractEntity2 id db
请注意,数据库中没有存储类型为Player的对象,而是只存储组成Player的组件,即位置和健康。(任何具有与之相关的位置和健康状况的实体都可以表示为玩家。)


有什么方法可以实现这样的目标吗?

我做了一些研究,我想我已经找到了我自己问题的答案:

不幸的是,我想在F#中做的事情似乎不可能,用户Gus很好地总结了原因:

恐怕没有办法向泛型添加子类型约束 基于F#中的另一个参数的类型参数。他们总是被认为是 如果相等,请参见规范表单类型的新约束:>'b为 再次解析为type='b

这种限制在C#中不存在,这使得互操作有时很麻烦。在F#语言建议github页面上有一个解决方案

换句话说,您不能编写这样的函数:

let foo<'T, 'U when 'T :> 'U> () = …
let foo()=…
这意味着你也不能这么做:

let foo2<'T, 'T2, 'T3 when 'T :> Tuple<'T2, 'T3>> () = …
让foo2元组>()=…
这基本上就是我想要的,除了额外的类型推断,这样就不用键入全部内容了:

let callFoo2 = foo2<int*string, int, string> ()
让callFoo2=foo2()
你可以这样写,从T1中推断出T2和T3:

let callFoo2Differently = foo2<int*string> ()
让callfooddifferentily=foo2()

为什么需要使用泛型?你不能让类型推断决定函数的类型吗?或者使用类型注释(如果需要或需要)。当然,您可能需要为EntityID、Position和Health定义类型(看起来您已经这样做了,但没有在这里透露类型定义)。@ScottHutchinson我需要泛型能够为不同类型重用相同的函数:可以从extractEntity2中删除泛型并将其重命名为“extractPlayer”,将所有对“T2”和“T3”的引用替换为位置和健康。但是这个新的extractPlayer函数只能提取一个播放器,你必须为extractMonster和ExtractFloorArtile等创建几乎相同的函数……关于类型推断:我的示例代码中函数的返回类型可能可以推断,我只是把它们包含在清晰的地方。考虑让玩家/怪物/地板是一个泛型类,而不是一个元组。看,我认为这个问题可能与你正在尝试做的事情有关。
let callFoo2 = foo2<int*string, int, string> ()
let callFoo2Differently = foo2<int*string> ()