如何在F#中正确使用管道和curring?

时间:2018-09-21 17:42:19

标签: f# functional-programming .net-core

我正在阅读有关F#的信息,并试图将其应用于我的日常工作。 我已经能够借助NuGet的FSharp.Data加载CSV文件,但是我认为它是一种命令式样式。现在,我正在尝试应用功能构造,并尝试了以下方法:

open System
open System.IO
open FSharp.Data

[<EntryPoint>]
let main argv =
  let data =
    argv.[0]
    |> Path.Combine Environment.CurrentDirectory
    |> CsvFile.Load

  printfn "%A" data.Headers

  0

我在这里想念的是什么? 在我的脑海中,argv.[0]传递给了Path.Combine Environment.CurrentDirectory的结果,该结果被咖喱已将当前目录作为第一个path,然后将合并的结果提供给CsvFile.Load。 我收到|>并发错消息了吗?

2 个答案:

答案 0 :(得分:4)

由于Path.Combine是一个采用params数组的C#函数,因此无法将参数通过管道传递到非零位置。您可以创建一个数组并将其传递给它:

[|Environment.CurrentDirectory; argv.[0]|]
|> Path.Combine
|> CsvFile.Load  

答案 1 :(得分:1)

您的管道看起来正确,因此我怀疑您的问题是CsvFile.Load is documented to take a URI, not a filename。为了检查您是否获得正确的文件名,我首先将CsvFile.Load替换为管道中的printfn "Got result: %s",以检查您是否获得了期望的文件名。然后,如果这是您期望的(我想会的),则可以在管道中添加另一步:

[<EntryPoint>]
let main argv =
  let data =
    argv.[0]
    |> Path.Combine Environment.CurrentDirectory
    |> sprintf "file://%s"  // Convert filename to URI
    |> CsvFile.Load

  printfn "%A" data.Headers

  0

由于您显然是F#的新手,所以我将稍微扩展这些步骤,以便您可以确认自己的直觉是正确的:

    argv.[0]
    |> Path.Combine Environment.CurrentDirectory

这就像打电话给Path.Combine Environment.CurrentDirectory argv.[0]

    argv.[0]
    |> Path.Combine Environment.CurrentDirectory
    |> sprintf "file://%s"  // Convert filename to URI

这就像打电话给sprintf "file://%s" (Path.Combine Environment.CurrentDirectory argv.[0])

    argv.[0]
    |> Path.Combine Environment.CurrentDirectory
    |> sprintf "file://%s"  // Convert filename to URI
    |> CsvFile.Load

这就像打电话给CsvFile.Load (sprintf "file://%s" (Path.Combine Environment.CurrentDirectory argv.[0]))

从您在问题中所说的来看,这似乎与您的理解相符,因为您正确地理解了管道。因此,只需传递CsvFile.Load而不是文件名的URI,就可以了。