Generics 如何解决静态解析类型参数的递归映射中的奇怪类型错误?(第2部分)

Generics 如何解决静态解析类型参数的递归映射中的奇怪类型错误?(第2部分),generics,static,f#,inline,Generics,Static,F#,Inline,我尝试了两种变体,它们都有相同的问题 type CudaScalar<'t> = CudaScalar of name: string with member t.Name = t |> fun (CudaScalar name) -> name type TypePrinter<'t>() = class end let inline print_type x = ((^T or ^in_) : (static member PrintT

我尝试了两种变体,它们都有相同的问题

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

type TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter
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, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "
我在最后3行中看到了这一点(对于两种变体):

Script1.fsx(16,34):错误FS0193:类型约束不匹配。类型
“in_
与类型不兼容
FSI_0002.CudaScalar'
这让我很惊讶,因为这个错误并没有在Intellisense中出现,而是只有在我尝试在F#Interactive中运行它时才会出现。我不知道在这里该怎么办。我可能滥用了太多的类型系统,但我决心以无标记的方式完成这个Cuda编译器,不管怎样。我需要这样做,以便为以后的阶段传播类型信息

编辑:古斯塔沃的修复方案可行,但当我再深入一点时,它又坏了

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 TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter with
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr1D< ^t>) = 
        [|print_type (TypePrinter< ^t>()); "*"; t.Name|] |> String.concat " "

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 ", "
type CudaScalar=CudaAr1D of CudaScalar*名称:字符串
成员t.Name=t |>fun(CudaAr1D(|,Name))->Name

打字打印机我不确定我是否理解你的问题/你想达到什么目的

我不知道为什么你把函数插入到中间的类型中,在你之前的问题中是必要的,但是在这里我不这么认为。 如果按自然顺序编写,它将编译:

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

type TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter with
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "

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

我的意思是“延伸”两次。

我不确定我是否理解你的问题/你想达到什么目的

我不知道为什么你把函数插入到中间的类型中,在你之前的问题中是必要的,但是在这里我不这么认为。 如果按自然顺序编写,它将编译:

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

type TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter with
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "

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

我的意思是,“延伸”两次。

是的,非常感谢,没有你的专业知识我会迷路的。请看编辑。您的代码确实可以编译,但是添加一些额外的成员会使代码再次崩溃。我开始认为这不是制作迷你编译器的正确途径,即使理论上F#应该能够做到这一点。我很好奇,如果你能找到一个解决这个问题的方法。看到你的编辑。令人惊讶的是,这是有效的。我试着用这种方式扩展原始代码,它也可以编译。是的,但我再一次不能解释为什么。正如你所说,我在解决过载解决方案中的这种不一致方面有一些专业知识,因为它已经导致了很多年。如果你感兴趣,你也可以贡献这个库,通过这样做,你将学习所有这些常见的解决方法和一些更复杂的方法。你可以与其他人分享你正在努力实现的目标。从理论上讲,向F#guys汇报是正确的方法,你应该这样做,但我认为他们不太可能很快解决这些问题,除非投稿人提交解决方案。我想如果我今年有时间,我会尝试重新设计约束求解器,使其更一致,从而更可用。但是要做到这一点需要很多时间。好吧,总的来说,如果我们共同努力,我们能取得的成绩会更好。你可以用你的问题开始一个问题,描述你想做什么,然后如果你发布一个链接,我也可以看看你的库。这样我们可以互相帮助。是的,非常感谢你,没有你的专业知识我会迷路的。请看编辑。您的代码确实可以编译,但是添加一些额外的成员会使代码再次崩溃。我开始认为这不是制作迷你编译器的正确途径,即使理论上F#应该能够做到这一点。我很好奇,如果你能找到一个解决这个问题的方法。看到你的编辑。令人惊讶的是,这是有效的。我试着用这种方式扩展原始代码,它也可以编译。是的,但我再一次不能解释为什么。正如你所说,我在解决过载解决方案中的这种不一致方面有一些专业知识,因为它已经导致了很多年。如果你感兴趣,你也可以贡献这个库,通过这样做,你将学习所有这些常见的解决方法和一些更复杂的方法。你可以与其他人分享你正在努力实现的目标。从理论上讲,向F#guys汇报是正确的方法,你应该这样做,但我认为他们不太可能很快解决这些问题,除非投稿人提交解决方案。我想如果我今年有时间,我会尝试重新设计约束求解器,使其更一致,从而更可用。但是要做到这一点需要很多时间。好吧,总的来说,如果我们共同努力,我们能取得的成绩会更好。你可以用你的问题开始一个问题,描述你想做什么,然后如果你发布一个链接,我也可以看看你的库。这样我们可以互相帮助。
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 TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter with
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "
    static member inline PrintArg(_: ArgsPrinter, t: CudaAr1D< ^t>) = 
        [|print_type (TypePrinter< ^t>()); "*"; t.Name|] |> String.concat " "

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 ", "
type CudaScalar<'t> = CudaScalar of name: string with
    member t.Name = t |> fun (CudaScalar name) -> name

type TypePrinter<'t>() = class end

let inline print_type x =
    ((^T or ^in_) : (static member PrintType: TypePrinter< ^in_> -> string) x)

type TypePrinter with
    static member inline PrintType(_: TypePrinter<float32>) = "float32"
    static member inline PrintType(_: TypePrinter<int>) = "int"

type ArgsPrinter = ArgsPrinter with
    static member inline PrintArg(_: ArgsPrinter, t: CudaScalar< ^t>) = 
        [|print_type (TypePrinter< ^t>()); t.Name|] |> String.concat " "

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