К сожалению, вы не можете решить эту проблему с помощью встроенного сопоставления с образцом.
Единственный способ узнать, является ли значение obj
некоторой функцией F #, - это использовать F # Reflection и вызвать метод 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
Вы могли бы инкапсулировать поведение в активном шаблоне F #, чтобы сделать синтаксис более приятным (и использовать сопоставление с образцом в типах). Однако другая проблема заключается в том, что это не дает вам функцию, которую вы могли бы использовать для ее динамического вызова. Я не думаю, что для этого есть встроенная библиотечная функция, поэтому вам, вероятно, потребуется использовать .NET отражение для динамического вызова метода Invoke
.
РЕДАКТИРОВАТЬ : были похожие вопросы по SO. Общая проблема заключается в том, что вы сопоставляете некоторые (любые) экземпляры определенного универсального типа, поэтому такая же проблема возникает со списками и т. Д. См., Например: