2011-11-17 16 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"])) 

प्रिंट "विफल" दो बार, जैसा कि मुझे लगता है कि यह चाहिए, क्योंकि मैं मुझे obj -> list<String> फ़ंक्शन दे रहा हूं, जो obj -> list<obj> नहीं है। क्या उन्हें मैच बनाने का कोई तरीका है? मैं प्रत्येक सूची को list<obj> में से गुमनाम कार्य करने से पहले उजागर कर सकता हूं, या मैं इसे सूची में रखने से पहले obj पर सब कुछ बढ़ा सकता हूं।एफ # पैटर्न मिलान: मिलान कार्य/उपप्रकारों की सूचियां?

इनमें से कोई भी काम करता है और इसे मेल खाता है, लेकिन मैंने सोचा कि यह समस्या थी कि कॉन्वर्सिस/contravariance पहले ही हल हो गया था? अगर मुझे गलती है तो मुझे सही करें

+2

एफ # सह/contravariance का समर्थन नहीं करता है। – Daniel

उत्तर

7

दुर्भाग्यवश, आप किसी अंतर्निहित पैटर्न मिलान का उपयोग करके इसे हल नहीं कर सकते हैं।

यह पता लगाने का एकमात्र तरीका है कि obj मान कुछ F # फ़ंक्शन F # प्रतिबिंब का उपयोग करना है और इस प्रकार FSharpType.IsFunction विधि को कॉल करें। आप इस तरह अपने उदाहरण में मामले के लिए जाँच कर सकते हैं:

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 

आप वाक्य रचना थोड़ा अच्छे बनाने के लिए (और पैटर्न प्रकार पर मिलान का उपयोग करें) एक एफ # सक्रिय पैटर्न में व्यवहार संपुटित सकता है। हालांकि, एक और समस्या यह है कि यह आपको एक ऐसा फ़ंक्शन नहीं देता है जिसका उपयोग आप गतिशील रूप से फ़ंक्शन को वास्तव में करने के लिए कर सकते हैं। मुझे नहीं लगता कि इसके लिए एक अंतर्निहित लाइब्रेरी फ़ंक्शन है, इसलिए आपको शायद Invoke विधि को गतिशील रूप से कॉल करने के लिए .NET प्रतिबिंब का उपयोग करने की आवश्यकता होगी।

EDIT: SO पर समान संबंधित प्रश्न हैं। सामान्य समस्या यह है कि आप कुछ (कोई भी) एक विशिष्ट सामान्य प्रकार के इन्स्टेन्शियशन के खिलाफ मिलान कर रहे हैं तो एक ही मुद्दा सूचियों आदि उदाहरण के लिए देखें के साथ उठता है:

संबंधित मुद्दे