【发布时间】:2016-11-08 20:59:55
【问题描述】:
在下面的代码中,我想使用一个变量的类型来实例化一个模板类,最终作为一个泛型变量传递给一个函数,但即使这种更简单的形式也不起作用:
type saveXY<'a when 'a:comparison> (x:'a,y:'a) =
member this.X = x
member this.Y = y
member this.lessThan () = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver1 = new saveXY<int>(x1,y1) // Good
printfn "%A" (saver1.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver2 = new saveXY<float>(x2,y2) // Good
printfn "%A" (saver2.lessThan())
let saver3 = new saveXY<x2.GetType()> (x2,y2) // No Good, see errors
0
但是,对于下面的saver3,我得到了(并且我找不到关于 FS1241 的信息):
...\Program.fs(23,39): error FS0010: Unexpected symbol '(' in type arguments. Expected ',' or other token.
...\CompareProblem\Program.fs(23,39): error FS1241: Expected type argument or static argument
如果您删除 saveXY 上的模板,则 saver2 会出错,因为 saver1 会导致 saveXY 类参数被限制为整数。
我还尝试将 x 和 y 简单地声明为 obj,但这不起作用。我怀疑问题在于这根本不可能,
也就是说,如果类参数类型是通用的,则它们派生一次(从第一次使用开始)。另一方面,也许我错过了什么。
有没有办法使用基于变量的类型(在编译时可确定)作为 F# 中的类型模板参数?是否有另一种方法来创建能够处理/存储通用值的类型?
更新:根据 Lee 的建议,这是可行的,如果您将类模板化,然后使用 <_> 实例化它就可以了:
type saveXY<'a when 'a:comparison> (x:'a, y:'a) =
member this.X = x
member this.Y = y
member this.lessThan () = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver3 = new saveXY<_> (x1,y1) // works, 'a is int
printfn "%A" (saver3.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver3 = new saveXY<_> (x2,y2) // works, 'a is float
printfn "%A" (saver3.lessThan())
System.Console.ReadKey() |> ignore // wait for a key
0
但是为什么我需要模板类类型,就像我上面建议的那样?当我使用<_> 时,编译器似乎在推断类型,所以为什么我不能简单地使用(就像我对函数一样):
type saveXY(x, y) = // x and y are generic, no? They only require comparison, yes?
member this.X = x
member this.Y = y
member this.lessThan () = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver3 = new saveXY (x1,y1) // works
printfn "%A" (saver3.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver3 = new saveXY (x2,y2) // But this FAILS with error FS0001
printfn "%A" (saver3.lessThan())
System.Console.ReadKey() |> ignore // wait for a key
0
【问题讨论】:
-
不,你不能像这样指定类型参数,虽然你已经静态知道
x2和y2的类型,所以你的用例不清楚。 -
不是很清楚你到底想做什么:你是否试图构建代码,用在编译时未知的通用参数实例化你的类,或者您是否只想说“
x2是什么类型,请使用它”,然后让编译器弄清楚? -
它是:只是想说“无论 x2 是什么类型,请使用它”,并让编译器弄清楚? 案例 - 在上面的示例中,我想
saver3用浮点模板类型实例化,因为x2是浮点数。在实际代码中,x2 将是泛型类型的函数参数,但该函数使用不同的编译时类型实例化
标签: class templates generics f#