错误 FS0001:类型 'string -> seq<unit>' 与类型 'seq<'a>' 不兼容

Error FS0001: The type 'string -> seq<unit>' is not compatible with the type 'seq<'a>'

我很难理解 F# 中的错误消息,因为这是我第一次使用类型化的函数式语言。这是我的代码示例:

let getAllFiles (directory : string) =
    Directory.GetFiles(directory)
let getFileInfo =
    getAllFiles 
    |> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))

我收到以下错误消息:"Error FS0001: The type 'string -> seq' is not compatible with the type 'seq<'a>'"

我可以做哪些改变?提前谢谢你。

由于您正在组合函数,而不是将值从一个函数传递到另一个函数,因此您必须使用组合运算符 (>>) 而不是管道 (|>):

open System.IO

let getAllFiles (directory : string) =
    Directory.GetFiles(directory)

let getFileInfo =
    getAllFiles 
    >> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))

或者,您可以将参数显式化,然后使用管道:

open System.IO

let getAllFiles (directory : string) =
    Directory.GetFiles(directory)

let getFileInfo directory =
    directory
    |> getAllFiles
    |> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))

评论更新:

If I specifically want to get the file length, how should I write it instead?

open System.IO

let getAllFiles directory =
    Directory.GetFiles directory 

let getFileInfos =
    getAllFiles
    >> Seq.map (fun fileName -> (fileName, FileInfo fileName))


let getFileLengths =
    getFileInfos
    >> Seq.map (fun (fileName, fileInfo) -> fileName, fileInfo.Length)

如果你想获取目录中所有文件的所有文件长度,你可以像上面的代码一样使用 getFileLengths 函数。注意我修改了getFileInfo.

的名字

更新第二条评论:

I would like to group the tuples according to the length of each file using Seq.groupBy. How may I go about doing so?

函数 removeSingletonGroups 删除所有只包含一个值的组。

函数getFilesGroupedByLength首先使用Seq.groupBy创建以文件长度为键的组,然后使用Seq.map从值中删除文件长度,因此每个的值group 只是一个文件名列表。最后它使用 removeSingletonGroups 清除所有只包含一个文件的组。

let removeSingletonGroups groupedSeq =
    groupedSeq
    |> Seq.filter (snd >> List.length >> (<>) 1)

let getFilesGroupedByLength =
    getFileLengths
    >> Seq.groupBy snd
    >> Seq.map (fun (fileLength, files) -> fileLength, files |> Seq.map fst |> List.ofSeq)
    >> removeSingletonGroups

最终(?)更新:

我刚刚看到你关于重复文件检查器的问题。我认为这种方法正是您要找的:

open System.IO

let getFilesOfDirectory directoryPath = 
    Directory.EnumerateFiles directoryPath

let getFileLength filePath =
    (FileInfo filePath).Length

let groupFilesByLength files =
    files
    |> Seq.groupBy getFileLength

let removeSingletonGroups groupedSeq =
    groupedSeq
    |> Seq.filter (fun (_, group) -> Seq.length group > 1)

let getDuplicateFileCandidates directoryPath =
    directoryPath
    |> getFilesOfDirectory
    |> groupFilesByLength
    |> removeSingletonGroups

您需要将目录提供给 getAllFiles 例如

let getFileInfo =
    getAllFiles "directory to search"
    |> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))

通常,当您遇到这样的错误时,函数类型 a -> ... -> b 与类型 b 不兼容,那么您没有为正在使用的函数提供足够的参数。