2011-11-17 14 views
5
let f (O: obj) = 
    match O with 
     | :? (obj -> list<obj>) -> "win" 
     | :? list<obj> -> "list!" 
     | _ -> "fail" 

Console.WriteLine(f(fun x -> ["lol"])) 
Console.WriteLine(f(["lol"])) 

drukuje "niepowodzenie" dwa razy, jak przypuszczam, powinien, ponieważ daje mi funkcję obj -> list<String>, która nie jest obj -> list<obj>. Czy jest jakiś sposób, żeby je dopasować? Mogłem podnieść każdą listę do postaci list<obj>, zanim wykonam z niej anonimową funkcję, lub przed opublikowaniem na liście mogę wszystko upchnąć na obj.F # Dopasowywanie wzorców: Pasujące funkcje/listy podtypów?

Każda z tych prac i sprawia, że ​​pasują, ale myślałem, że to był problem, że kowariancja/contrawariancja miała już rozwiązać? Popraw mnie, jeśli się mylę.

+2

F # nie obsługuje koinicjancji. – Daniel

Odpowiedz

7

Niestety, nie możesz tego rozwiązać za pomocą wbudowanego dopasowywania wzorca.

Jedynym sposobem, aby dowiedzieć się, czy wartość obj jest jakąś funkcją F #, jest użycie odbicia F # i wywołanie metody FSharpType.IsFunction na typie. Można sprawdzić w Twoim przypadku np tak:

open System  
open Microsoft.FSharp.Reflection  

let f (o : obj) = 
    let ty = o.GetType() 
    if FSharpType.IsFunction(ty) then 
    let tyFrom, tyTo = FSharpType.GetFunctionElements(ty) 
    if tyTo.IsGenericType && tyTo.GetGenericTypeDefinition() = typedefof<list<_>> then 
     printfn "win" 
    else 
     printfn "wrong function" 
    else 
    printfn "not a function" 

Console.WriteLine(f(fun x -> "lol")) // wrong function 
Console.WriteLine(f(fun x -> ["lol"])) // win 
Console.WriteLine(f(["lol"]))   // not a function 

Można upakować zachowanie w # aktywnego wzoru F aby składnię nieco ładniejszy (i użyć wzoru na dopasowanie typów). Jednak innym problemem jest to, że nie daje to funkcji, której można użyć do dynamicznego wywołania funkcji. Nie sądzę, że jest w tym wbudowana funkcja biblioteczna, więc prawdopodobnie będziesz musiał użyć funkcji .NET reflection, aby dynamicznie wywoływać metodę Invoke.

EDYCJA: Podobne pytania dotyczyły SO. Ogólnym problemem jest to, że jesteś dopasowanie przeciwko pewnym (dowolnym) instancji określonego typu rodzajowego, więc ten sam problem powstaje z listami itp Patrz na przykład:

Powiązane problemy