В F#: как получить список имен файлов в каталоге; ожидаемая единица имеет строку

Я только начинаю с F#, поэтому я решил попробовать несколько простых задач.

Здесь перечислены полные пути к файлам xml в каталоге:

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (printfn "%s")

Но я хочу только имена файлов, поэтому я попробовал:

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")

Это не скомпилируется. Это дает ошибку:

Ожидалось, что это выражение будет иметь тип unit
но здесь есть строка типа

Я искал примеры, но ничего не смог найти. Я явно упускаю что-то простое и фундаментальное, но что?

1 ответ

Решение

Поскольку вы новичок, проще всего исправить ошибки, если подумать об утверждениях, подобных математическим утверждениям, которые могут быть построены из более простых функций, но которые также могут быть разбиты на части.

Таким образом, разбив вашу проблему на части, вы можете получить более мелкую ошибку, которую легче решить.

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")

учитывается отдельно

let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.iter (System.IO.Path.GetFileName) directoryArray
(printfn "%s") nameArray 

теперь ошибки должны быть намного легче понять

Если мы посмотрим на подпись Array.iter который iter : ('T -> unit) -> 'T [] -> unit мы видим, что ему нужна функция ('T -> unit) который принимает тип и возвращает unit это означает, что ничего не вернуть, в этом случае печать будет работать, однако вы не хотите возвращать ничего, вы хотите преобразовать массив каталогов в массив имен файлов. Так Array.iter не будет работать, и вам нужна функция Array, которая применяет функцию к каждому элементу в массиве и возвращает новый Array, Array.map Является ли это map : ('T -> 'U) -> 'T [] -> 'U [] Чтобы лучше понять функции Array и посмотреть, как они работают, можно добавить lambda function,

Аналогично с (printfn "%s"); можно добавить лямбда-функцию для передачи значения.

let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.map (fun x -> (Path.GetFileName(x))) directoryArray
Array.iter (fun x -> printfn "%s" x) nameArray

Теперь мы можем упростить утверждения, используя |>

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map (fun x -> (Path.GetFileName(x)))
|> Array.iter (fun x -> printfn "%s" x)

и снова упростить, удалив lambdas

open System.IO

Directory.GetFiles("c:\\tmp", "*.xml") 
|> Array.map Path.GetFileName 
|> Array.iter (printfn "%s") 
Другие вопросы по тегам