如何使用静态解析类型参数解决递归映射中的奇怪类型错误? (第 2 部分)
How to resolve the strange type error in a recursive map with statically resolved type parameters? (pt. 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 编译器。我需要这样,以便为以后的阶段传播类型信息。
编辑:Gustavo 的修复有效,但当我更进一步时它又坏了。
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 ", "
再一次,在最后两行中,我出现了与 pt 中完全相同的错误。其中 1 个。我在这里要做的是制作嵌入式 Cuda DSL 的一部分。我这样做而不是使用 DU 的原因是因为对于 DU,我必须将接口作为一个单独的部分。如果我这样做,我将能够编写 cuda_map (fun x -> x*x)
并编译它,因为类型信息将会存在。上面的片段特别应该打印出内核方法的参数。
如果这是 Haskell 我会使用 typeclasses+HKTs+tagless 风格来做到这一点,在 Ocaml GADTs 中,但在 F# 中,对我来说唯一现实的选择是模仿 finally tagless style 使用静态解析类型参数,但我没有指望有编译器错误。
我打算将此线程传递给我打开的问题。
我不确定我是否理解你的意思question/what你想达到什么目的。
我不知道你为什么要在类型中间插入函数,在你之前的问题中这是必要的,但在这里我不这么认为。
如果你按照自然顺序编写,它会编译:
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 ", "
我的意思是,'extending' 两次。
我尝试了两种变体,它们都有同样的问题。
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 编译器。我需要这样,以便为以后的阶段传播类型信息。
编辑:Gustavo 的修复有效,但当我更进一步时它又坏了。
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 ", "
再一次,在最后两行中,我出现了与 pt 中完全相同的错误。其中 1 个。我在这里要做的是制作嵌入式 Cuda DSL 的一部分。我这样做而不是使用 DU 的原因是因为对于 DU,我必须将接口作为一个单独的部分。如果我这样做,我将能够编写 cuda_map (fun x -> x*x)
并编译它,因为类型信息将会存在。上面的片段特别应该打印出内核方法的参数。
如果这是 Haskell 我会使用 typeclasses+HKTs+tagless 风格来做到这一点,在 Ocaml GADTs 中,但在 F# 中,对我来说唯一现实的选择是模仿 finally tagless style 使用静态解析类型参数,但我没有指望有编译器错误。
我打算将此线程传递给我打开的问题。
我不确定我是否理解你的意思question/what你想达到什么目的。
我不知道你为什么要在类型中间插入函数,在你之前的问题中这是必要的,但在这里我不这么认为。
如果你按照自然顺序编写,它会编译:
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 ", "
我的意思是,'extending' 两次。