Mam pewne dziwne efekty podczas próby uruchomienia kodu f # poprzez odbicie.
Biorąc pod uwagę następujące rodzajeDziwny błąd odbicia na wnioskowanym typie
type Box<'a, 'b> = Box of 'a * 'b
i tę funkcję
//iToS :: Box<'a,'b> -> Box<string,'b>
let iToS (Box (i, v)) = Box ((sprintf "%A" i), v)
mogę łatwo i poprawnie uruchomić następujący kod
let r01 = iToS (Box (1, 1))
Jednak muszę uruchomić tę funkcję na ostrych krawędziach moich granic systemowych i jedynym sposobem, aby to zrobić, jest powrót do użycia refleksji.
Stworzyłem więc tę funkcję, która powinna przyjąć funkcję podobną do powyższej oraz rekord danego typu i zastosować go.
let convert<'t> (f:Quotations.Expr) (v:'a) : 't =
let methi e =
let rec methi' e =
match e with
| Call (x, mi, y) -> mi
| Lambda (_, body) -> methi' body
| _ -> failwith <| sprintf "not a function %A" e
methi' e
let apply f v =
let m = methi f
m.Invoke(null, [|box v|])
apply f v :?> 't
Jeśli teraz uruchomię to tak jak poniżej.
let r10 = (convert<Box<string, int>> <@ iToS @>) (Box (1, 1))
otrzymuję następujący błąd
System.ArgumentException : Object of type 'Box`2[System.Int32,System.Int32]' cannot be converted to type 'Box`2[System.Object,System.Object]'.
at System.RuntimeType.CheckValue (System.Object value, System.Reflection.Binder binder, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) [0x0007d] in <8cd55ece525b4760b63de40980e005aa>:0
at System.Reflection.MonoMethod.ConvertValues (System.Reflection.Binder binder, System.Object[] args, System.Reflection.ParameterInfo[] pinfo, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) [0x0007f] in <8cd55ece525b4760b63de40980e005aa>:0
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00014] in <8cd55ece525b4760b63de40980e005aa>:0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <8cd55ece525b4760b63de40980e005aa>:0
at convert[t] (Microsoft.FSharp.Quotations.FSharpExpr f, Box`2[a,b] v) [0x00006] in <5831a15618eafa12a745038356a13158>:0
at test convert() [0x000e6] in <5831a15618eafa12a745038356a13158>:0
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00038] in <8cd55ece525b4760b63de40980e005aa>:0
kto próbuje przekształcić coś do Box<obj, obj>
i dlaczego?
Każda pomoc jest mile widziana
PS: Niektóre wyjaśnienia ;-)
a) jest to wyraźnie pytanie o użyciu odbicia w kontekście F #
b) Tak, wiem, że mój prawdziwy problem może być rozwiązany bez refleksji i już to zrobiłem. Zwiększa rozmiar mojego kodu o 40% z łatwością.
c) tak, wiem, że odbicie jest wolne od psa. Jestem gotów, aby handlować prędkością (nie potrzebuję) dla czystszego kodu.
cześć, dzięki za odpowiedź - niestety nie działa :-( 'let convert (f: Quotations.Expr <'t -> 'a>) (v:' a): 't' nawet nie skompiluje, podczas gdy' let convert <'t, 'a> (f: Quotations.Expr) (v: 'a):' t' otrzymuje taki sam błąd jak poprzednio. Dodatkowo największym problemem jest to, że nie mogę ustawić typów jako parametrów ogólnych, ponieważ nie mam wtedy (przynajmniej nie w tej części programu) – robkuz
Myślę, że typy są w złej kolejności w odpowiedzi. Czy mógłbyś spróbować 'let convert (f: Quotations.Expr <'a -> 't>) (v:' a): 't ='? –
Dzięki! Naprawię tę literówkę. – gsomix