Почему вывод типа F# не может справиться с этим?
-
20-08-2019 - |
Вопрос
У меня есть последовательность 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
?
Решение
Вывод типа работает слева направо.Вот тут-то и пригодится оператор конвейера;если вы уже знаете тип «фис», то напишите его как
fis |> Seq.map (fun fi -> fi.Name)
и вывод работает на вас.
(Вообще говоря, выражения вида
o.Property
o.Method args
требуется, чтобы был известен тип «о» априори;для большинства других выражений, когда тип не закреплен, система вывода может «перемещать ограничение», которое можно решить позже, но для этих случаев не существует ограничений вида «все типы со свойством с именем P» или «все типы с методом с именем M» (например, утиная типизация), которые можно отложить и решить позже.Так что вам нужна эта информация сейчас, иначе вывод сразу же потерпит неудачу.)
См. также обзор вывода типа в F#.