Почему метод F # не может обрабатывать это?

У меня есть последовательность FileInfo, но я только забочусь о их строковых именах, поэтому мне нужна последовательность строк. Сначала я попробовал что-то вроде этого:

Seq.map (fun fi -> fi.Name) fis

Но почему-то вывод типа F # недостаточно хорош, чтобы позволить это, и заставил меня явно указать тип "fi":

Seq.map (fun (fi : FileInfo) -> fi.Name) fis

Зачем нужна аннотация? Если известно, что fis : seq<FileInfo> и что Seq.map : ('a -> 'b) -> seq<'a> -> seq<'b>, то не следует ли выводить, что тип лямбда-выражения равен FileInfo -> 'b, а затем, из fi.Name : string, далее следует, что его тип FileInfo -> string?

Ответы

Ответ 1

Тип вывода работает слева направо. Именно здесь полезен оператор трубопровода; если вы уже знаете тип 'fis', тогда напишите его как

fis |> Seq.map (fun fi -> fi.Name)

и вывод работает для вас.

(В общем случае выражения вида

o.Property
o.Method args

требуется, чтобы тип a был известен априори; для большинства других выражений, когда тип не закреплен, система вывода может "плавать ограничение", которая может быть решена позже, но для этих случаев нет ограничений формы "все типы с свойством с именем P" или 'все типы с методом M' (например, утиная печать), которые могут быть отложены и решены позже. Таким образом, вам нужна эта информация сейчас, или вывод немедленно сработает.)

См. также обзор вывода типа в F #.