2017-01-23 33 views
9
type CudaInnerExpr<'t> = CudaInnerExpr of expr: string with 
    member t.Expr = t |> fun (CudaInnerExpr expr) -> expr 

type CudaScalar<'t> = CudaScalar of name: string with 
    member t.Name = t |> fun (CudaScalar name) -> name 

type CudaAr1D<'t> = CudaAr1D of CudaScalar<int> * name: string with 
    member t.Name = t |> fun (CudaAr1D (_, name)) -> name 

type CudaAr2D<'t> = CudaAr2D of CudaScalar<int> * CudaScalar<int> * name: string with 
    member t.Name = t |> fun (CudaAr2D (_, _, name)) -> name 

type ArgsPrinter = ArgsPrinter with 
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar<float32>) = sprintf "float %s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar<int>) = sprintf "int %s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr1D<float32>) = sprintf "float *%s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr1D<int>) = sprintf "int *%s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr2D<float32>) = sprintf "float *%s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr2D<int>) = sprintf "int *%s" t.Name 

    static member inline PrintArg(_: ArgsPrinter, (x1, x2)) = 
     let inline print_arg x = 
      let inline call (tok : ^T) = ((^T or ^in_) : (static member PrintArg: ArgsPrinter * ^in_ -> string) tok, x) 
      call ArgsPrinter 
     [|print_arg x1;print_arg x2|] |> String.concat ", " 
    static member inline PrintArg(_: ArgsPrinter, (x1, x2, x3)) = 
     let inline print_arg x = 
      let inline call (tok : ^T) = ((^T or ^in_) : (static member PrintArg: ArgsPrinter * ^in_ -> string) tok, x) 
      call ArgsPrinter 
     [|print_arg x1;print_arg x2;print_arg x3|] |> String.concat ", " 

在行static member inline PrintArg(_: ArgsPrinter, (x1, x2, x3)) =,表达(x1, x2, x3)给了我以下错误:如何解决具有静态解析类型参数的递归映射中的奇怪类型错误?

Script1.fsx(26,52): error FS0001: This expression was expected to have type 
    'in_  
but here has type 
    'a * 'b * 'c 

任何想法是在这里做,使这项工作?

+1

如果您明确指定'PrintArg'的类型参数,会发生什么? –

+1

@FyodorSoikin它不会工作,因为F#解析器将拒绝读取名义类型上的静态约束的签名。这将在未来的F#版本中被允许。 – Gustavo

回答

9

想要做这样的事情在我看来:

... 

    static member inline PrintArg(_: ArgsPrinter, t: CudaAr2D<float32>) = sprintf "float *%s" t.Name 
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr2D<int>) = sprintf "int *%s" t.Name 

let inline print_arg x = 
    let inline call (tok : ^T) = ((^T or ^in_) : (static member PrintArg: ArgsPrinter * ^in_ -> string) tok, x) 
    call ArgsPrinter  

type ArgsPrinter with 
    static member inline PrintArg(_: ArgsPrinter, (x1, x2)) = [|print_arg x1;print_arg x2|] |> String.concat ", " 
    static member inline PrintArg(_: ArgsPrinter, (x1, x2, x3)) = [|print_arg x1;print_arg x2;print_arg x3|] |> String.concat ", " 

您在类型中定义的通用功能,因为你会使用它的最后两个重载,这将成为一种'递归重载'。

请注意,这种技术目前在FSharpPlus使用,实际上是一种简化的技术。

最后请注意,你的解决方案对我来说似乎也是正确的(尽管更详细),但由于某种原因,F#编译器感到困惑,我无法向你解释为什么,但遇到了像这样的许多情况,我所能做的就是找到一个最小的repro,一个解决方法并将它报告给F#的人。约束求解器中还有很多事情需要解决。

+0

我记得前一段时间读到上面的技术对扩展方法不起作用,所以我没有尝试过,但我猜这是错误的。我甚至检查它是否适用于嵌套元组,并且它确实如此。谢谢。 –

+4

你是对的,它在扩展方法中不起作用,但是如果它们在同一个文件中,它们不会被编译为扩展方法。 – Gustavo

+0

我应该这样报告还是要做?或者这种错误已经报道? –

相关问题