2017-01-23 98 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 ", " 

W linii static member inline PrintArg(_: ArgsPrinter, (x1, x2, x3)) = wyrażenie (x1, x2, x3) daje mi następujący błąd:Jak rozwiązać dziwny błąd typu na mapie rekurencyjnej z statycznie rozwiązanymi parametrami typu?

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

pojęcia, co zrobić, żeby to działało?

+1

Co się stanie, jeśli wyraźnie określisz parametry typu 'PrintArg'? –

+1

@FyodorSoikin to nie działa, ponieważ parser F # odrzuci odczytywanie sygnatury statycznego ograniczenia na typie nominalnym. To będzie dozwolone w nadchodzącej wersji F #. – Gustavo

Odpowiedz

9

Wydaje mi się, że chcesz zrobić coś takiego:

... 

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

zdefiniować funkcję rodzajowe w środku typu, ponieważ można go używać przez ostatnie dwa przeciążeń, które staną się rodzajem "przeciążeń rekursywnych".

Zauważ, że to technika używana obecnie w FSharpPlus, w rzeczywistości uproszczenie techniki.

Wreszcie, wydaje mi się, że twoje rozwiązanie wydaje mi się poprawne (chociaż bardziej szczegółowe), ale z jakiegoś powodu kompilator F # jest zdezorientowany, nie mogę ci wyjaśnić, ale spotkałem wiele sytuacji takich jak ta i wszystko, co mogę zrobić, to znajdź minimalne repro, obejście i zgłoś je do facetów z F #. W rozwiązaniu Wiążącym jest jeszcze wiele rzeczy do rozwiązania.

+0

Pamiętam, że jakiś czas temu czytałem, że powyższa technika nie działa na metodach rozszerzających, więc nie próbowałem tego, ale myślę, że to było złe. Sprawdziłem nawet, czy działa na zagnieżdżonych krotkach i to działa. Dzięki. –

+4

Masz rację, nie działa w metodach rozszerzeń, ale nie są one kompilowane jako metody rozszerzeń, jeśli znajdują się w tym samym pliku. – Gustavo

+0

Czy powinienem to zgłosić, czy chcesz to zrobić? Czy jest już zgłoszony tego rodzaju błąd? –