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



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

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 " "

type CudaScalar<'t> = CudaScalar of name: string with
member t.Name = t |> fun (CudaScalar name) -> name
type TypePrinter = TypePrinter
let inline print_type x =
let call (tok: ^T) = ((^T or ^in_) : (static member PrintType: TypePrinter * ^in_ -> string) tok, x)
call TypePrinter
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 Unchecked.defaultof< ^t>; t.Name|] |> String.concat " "

起初,我得到了与上一个问题完全相同的错误,但在我删除后:

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 ", "

我在最后3行中得到了这个(对于两种变体):

Script1.fsx(16,34): error FS0193: Type constraint mismatch. The type 
'in_    
is not compatible with type
FSI_0002.CudaScalar<'a>    
The type ''in_' does not match the type 'FSI_0002.CudaScalar<'a>'

这让我很惊讶,因为这个错误不会在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 ", "

再一次,在最后两行中,我发现了与第1行完全相同的错误。我在这里要做的是制作一个嵌入式Cuda DSL的一部分。我之所以这样做而不是使用DU,是因为有了DU,我必须将接口作为一个单独的部分。如果我这样做,我将能够编写cuda_map (fun x -> x*x)并编译它,因为类型信息将存在。特别是上面的片段应该打印出内核方法的参数。

如果这是Haskell,我会在Ocaml GADT中使用typeclasses+HKTs+无标记样式来实现,但在F#中,我唯一现实的选择是使用静态解析的类型参数来模仿最终的无标记样式,但我没有指望会有编译器错误。

我打算把这条线索也传递给我打开的问题。

我不确定我是否理解你的问题/你想实现什么。

我不知道你为什么在类型的中间插入函数,在你之前的问题中,这是必要的,但这里我不这么认为

如果你按照它编译的自然顺序写它:

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 ", "

我的意思是,"延长"两次。

相关内容

最新更新