Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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
Class F#模板中编译时可派生类型的使用_Class_Templates_Generics_F# - Fatal编程技术网

Class F#模板中编译时可派生类型的使用

Class F#模板中编译时可派生类型的使用,class,templates,generics,f#,Class,Templates,Generics,F#,在下面的代码中,我想使用变量的类型实例化一个模板类,最终作为传递到函数中的泛型变量,但即使是这种更简单的形式也不起作用: 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 =

在下面的代码中,我想使用变量的类型实例化一个模板类,最终作为传递到函数中的泛型变量,但即使是这种更简单的形式也不起作用:

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 
如果删除
saveXY
上的模板,则
saver2
会出错,因为
saver1
会导致
saveXY
类参数被约束为int

我还尝试将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  
键入saveXY(x:a,y:a)=
请记住这个。X=X
成员:this.Y=Y
成员this.lessThan()=this.X忽略//等待密钥
0
但是,为什么我需要像我上面建议的那样对类类型进行模板化呢?当我使用
时,编译器似乎无论如何都在推导类型,所以为什么我不能简单地使用(就像我使用函数一样):

type saveXY(x,y)=//x和y是泛型的,不是吗?它们只需要比较,是吗?
请记住这个。X=X
成员:this.Y=Y
成员this.lessThan()=this.X忽略//等待密钥
0

如果您只想让编译器推断您可以使用的泛型参数的类型:

let saver3 = new saveXY<_>(x2, y2)

如果您只想让编译器推断泛型参数的类型,可以使用:

let saver3 = new saveXY<_>(x2, y2)
F#没有任何内置方法来实例化运行时已知类型的泛型代码。您总是可以通过反射来实现这一点,但这并不是很有用——如果您使用反射来创建它,您实际上将无法对该值做很多事情

在本例中,您可以将
LessThan
移动到单独的界面中:

type ILessThan = 
  abstract LessThan : unit -> bool

type SaveXY<'T when 'T:comparison> (x:'T,y:'T) =
  member this.X = x
  member this.Y = y
  interface ILessThan with 
    member this.LessThan () = 
      printfn "Comparing values of type: %s" (typeof<'T>.Name)
      this.X < this.Y
下面是一个如何工作的示例:

let lt = createSaveXY (typeof<float>) (box 3.0) (box 7.0)
lt.LessThan()
让lt=createSaveXY(typeof)(框3.0)(框7.0)
LessThan中尉()
但是正如我前面所说,这很少有用,也不是非常高效——所以,与其复制它,不如描述您试图解决的问题-可能有一个更好的解决方案。

F#没有任何内置方法来实例化运行时已知类型的泛型代码。您总是可以通过反射来实现这一点,但这并不是很有用——如果您使用反射来创建它,您实际上将无法对该值做很多事情

在本例中,您可以将
LessThan
移动到单独的界面中:

type ILessThan = 
  abstract LessThan : unit -> bool

type SaveXY<'T when 'T:comparison> (x:'T,y:'T) =
  member this.X = x
  member this.Y = y
  interface ILessThan with 
    member this.LessThan () = 
      printfn "Comparing values of type: %s" (typeof<'T>.Name)
      this.X < this.Y
下面是一个如何工作的示例:

let lt = createSaveXY (typeof<float>) (box 3.0) (box 7.0)
lt.LessThan()
让lt=createSaveXY(typeof)(框3.0)(框7.0)
LessThan中尉()

但正如我前面所说的,这很少有用,也不是非常高效-因此,与其复制它,不如尝试描述您试图解决的问题-可能有更好的解决方案。

不,您不能像这样指定类型参数,尽管您已经静态地知道
x2
y2
的类型,所以你的用例不清楚。不清楚你到底想做什么:你是想构建代码,用编译时未知的泛型参数来实例化你的类,还是只想说“不管x2是什么类型的,请使用它”,然后让编译器来解决它“无论x2是什么类型,请使用它“,让编译器解决它吗?案例-在上面的示例中,我希望使用浮点模板类型实例化
saver3
,因为
x2
是浮点。在实际代码中,x2将是泛型类型的函数参数,但如果函数是用不同的编译时类型实例化的,则不能像这样指定类型参数,尽管您已经静态地知道
x2
y2
的类型,所以你的用例不清楚。不清楚你到底想做什么:你是想构建代码,用编译时未知的泛型参数来实例化你的类,还是只想说“不管x2是什么类型的,请使用它”,然后让编译器来解决它“无论x2是什么类型,请使用它“,让编译器解决它吗?案例-在上面的示例中,我希望使用浮点模板类型实例化
saver3
,因为
x2
是浮点。在实际代码中,x2将是泛型类型的函数参数,但如果函数使用不同的编译时类型实例化,则第二种形式不起作用,但第一种形式起作用-请参见UPDATE@user1857742-您使用的是哪个版本的F#?第二种形式可能需要F#4I,我认为它的3.1—在Visual Studio 2013中,第二种形式不起作用,但第一种形式起作用—请参见UPDATE@user1857742-您使用的是哪个版本的F#?第二种形式可能需要F#4I,我想它的3.1版本-在Visual Studio 2013中,感谢您提供详细的答案-我不想重复
let lt = createSaveXY (typeof<float>) (box 3.0) (box 7.0)
lt.LessThan()