2017-01-23 4 views
1

私はこれについて2つのバリエーションを試しましたが、どちらも同じ問題を抱えています。静的に解決された型パラメータを持つ再帰的なマップで奇妙な型のエラーを解決するには? (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 " " 

最初に私はprevious questionのように正確に同じエラーを得たが、私は削除した後:

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

これは私にとって驚いたrエラーは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 ", " 

もう一度、最後の2行で、ptと同じエラーが表示されます。これの1。私がここでやろうとしているのは、埋め込まれたCuda DSLの一部です。私がDUを使うのではなく、このようにしている理由は、DUを使用すると、インターフェースを別の部分にする必要があるからです。このようにすれば、cuda_map (fun x -> x*x)と書くことができ、タイプ情報が存在するためコンパイルできます。上記の断片は、特に、カーネルのメソッドの引数を表示することになっています。これはHaskellのだった

なら、私はOCamlのGADTsで、それを行うには+ HKTs +タグなしスタイル型クラスを使用することだろうが、F#で私のための唯一の現実的な選択肢は、静的に解決型のparamsを使用してfinally tagless styleを模倣することですが、私はそうではありませんそこにはコンパイラエラーが数えられます。

このスレッドを私が開いた問題に渡すつもりです。

答えて

4

私はあなたの質問を理解しているかどうかわからない/何を達成しようとしていますか。

なぜ私はあなたが以前の質問では、必要だったが、ここで私はそうは思わないタイプの真ん中に関数を挿入したのか分からない。

あなたはそれがコンパイル自然な順序でそれを記述する場合:

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 

私は何かが欠けていた場合、私に知らせてください。このようにそれらを追加しようと、多くのオーバーロードを追加するあなたの試みの後

EDIT

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

私が意味する、二回 '拡張'。

+0

ありがとう、私はあなたの専門知識なしで失われるだろう。編集をご覧ください。あなたのコードは実際にはコンパイルされますが、いくつかの追加メンバーを追加すると、その事が再び破られます。私は理論的にF#が可能であっても、これがミニコンパイラを作る正しい道ではないと思っています。あなたがこれを回避する方法を見つけられるのであれば、私は不思議です。 –

+0

あなたの編集を見た。これがうまくいくのは驚くべきことです。私はこの方法で元のコードを拡張しようとしたが、それもコンパイルされます。 –

+1

はい、もう一度、私は本当に理由を説明することはできません。すでに述べたように、私は[FSharpPlus](https://github.com/gmpl/FSharpPlus)に貢献することはすでに何年も前から行われているため、これらの種類の不整合を作業負荷に分解する専門知識を持っています。興味があれば、図書館に寄稿することもできます。そうすることで、これらすべての一般的な回避策や複雑なものを学ぶことができます。また、達成しようとしていることを他の人と共有することも可能です。 – Gustavo

関連する問題