是否可以在 F# 的管道中使用实例方法?

Is it possible to use an instance method in a pipeline in F#?

是否可以在 F# 的管道中直接使用实例方法?我问的是一般情况,但这里有一个例子。

假设我试图在管道内将字符串转换为小写。 String.ToLower() 方法是一个带有签名 unit -> string 的实例方法。如果它是一个静态 string -> string 方法,您可以像这样在管道中使用它:"MyString" |> String.ToLower,但由于它是一个依赖于实例内容的实例方法,所以这是行不通的。

我知道有一些方法可以解决这个问题,例如使用 "MyString" |> String.map (fun x -> Char.ToLower(x)) 或定义方法 stringLower (input: string) = input.ToLower(),但我对直接在管道。

从上面重申,我并不是简单地要求一种将字符串转换为小写的方法。我在问是否有在管道中使用实例方法的通用方法。

"MyString" |> (fun x -> x.ToLower())

这是个人意见,但我觉得如果你想在管道中使用实例方法,为结果定义一个新变量总是更具可读性before操作然后直接使用实例方法。为什么不直接使用?

"MyString".ToLower()

以上是一个非常简单的案例,但假设您的实际用例是这样的:

let greeting = 
  [| "hi"; "there" |]
  |> String.concat " "
  |> fun x -> x.ToUpper()

在这里,有些人更喜欢在管道中使用 ToUpper 以这种方式编写代码。不过我不会这样做,只会写:

let greetingLow = [| "hi"; "there" |] |> String.concat " "
let greeting = greetingLow.ToUpper()

当通过管道传递的事物的类型发生变化时(例如,从这里的数组到字符串),这种事情经常发生。发生这种情况时,我发现打破管道更具可读性。

如果您经常使用某些功能,可以在模块中定义它们

[<RequireQualifiedAccess;
  CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module String =
    let inline toUpper (s: string) = s.ToUpper()

然后在管道中写入

let greeting =
  [| "hi"; "there" |]
  |> String.concat " "
  |> String.toUpper

缺点是您需要围绕现有实例方法编写精简包装器,并且还需要考虑重载。但是已经有为您定义它们的库(例如 F#+

有一个 suggestion 用于简化 属性 管道中的访问和方法调用。它原则上获得批准,但甚至还没有 RFC。它允许写类似

的东西
  [| "hi"; "there" |]
  |> String.Join(' ', _)
  |> _.ToUpper(CultureInfo.CurrentCulture)