Почему делает...
type IntDelegate = delegate of int -> unit
type ListHelper =
static member ApplyDelegate (l : int list) (d : IntDelegate) =
l |> List.iter (fun x -> d.Invoke x)
ListHelper.ApplyDelegate [1..10] (fun x -> printfn "%d" x)
не компилируют, когда:
type IntDelegate = delegate of int -> unit
type ListHelper =
static member ApplyDelegate (l : int list, d : IntDelegate) =
l |> List.iter (fun x -> d.Invoke x)
ListHelper.ApplyDelegate ([1..10], (fun x -> printfn "%d" x))
?
Единственная разница, которая является что во втором, ApplyDelegate
берет его параметры в качестве кортежа.
Эта функция берет слишком много аргументов или используется в контексте, где функция не ожидается
Я не смотрел спецификацию, чтобы подтвердить, но предполагаю, что неявное преобразование из «лямбда» в «именованный тип делегата» происходит только в "вызовы участников".
Вы всегда можете сделать преобразование явным:
ListHelper.ApplyDelegate [1..10] (IntDelegate(fun x -> printfn "%d" x))
(Диагностика ошибок довольно плохая; я запишу ошибку.)
РЕДАКТИРОВАТЬ:
Для чудаков ...
Да, spec говорит
8.13.6 Преобразования, ориентированные на тип, при вызовах членов Как описано в разделе Разрешение приложения метода (см. §14.4), два преобразования, ориентированных на тип {{ 1}} применяются при вызовах методов.
Если формальный параметр имеет тип делегата DelegateType, а фактический аргумент синтаксически является значением функции (весело ...), то параметр равен {{ 1}} интерпретируется так, как если бы он был написан new DelegateType (весело ...).
, что лямбда-выражения автоматически преобразуются в делегированные типы только при "вызовах членов". В случае каррированного члена первый переданный аргумент является вызовом члена, но затем он возвращает значение функции для применения второго аргумента, а вызовы функций не имеют этого правила неявного преобразования.