bohdan_trotsenko
bohdan_trotsenko

Reputation: 5367

F#: String.Join and |> operator

In F# interactive, I can use String.Join("+", ["a"; "b"]) successfully, but

["a"; "b"] |> String.Join "+"

produces an error:

Script1.fsx(79,15): error FS0001: This expression was expected to have type
    string list -> 'a    
but here has type
    string

How do I use String.Join passing a collection using pipeline?

P.S. The same problem is with lines |> File.WriteAllLines "filename.txt"

Upvotes: 58

Views: 19405

Answers (2)

Richiban
Richiban

Reputation: 5930

I thought I would weigh in with an alternative. The OP specifically asked about String.Join, and Tomas Petricek's answer is absolutely correct for that method (use String.concat from the F# library).

If you're talking about another method that takes tupled arguments but you want to use them as curried, you can use this helper function:

let partial f x y = f(x, y)

This allows you to pass a method to 'partial' and get back a curried function. Use it like this:

let partial f x y = f(x, y)
myCollection |> partial String.Join "&"

Upvotes: 25

Tomas Petricek
Tomas Petricek

Reputation: 243096

String.Join is a .NET method. When using a .NET method, F# views it as a function that takes a tuple as an argument (when calling it you write parameters as f(a, b)). The |> operator can be used with functions that use the curried form of parameters (and can be called by writing f a b).

You can use a function String.concat from the F# library (which does the same thing) instead:

["a"; "b"] |> String.concat "+"

EDIT File.WriteAllLines is the same case. If you want to use it as part of a pipeline, you can write an F# function that wraps the call:

let writeAllLines file (lines:seq<string>) =
  System.IO.File.WriteAllLines(file, lines)

In general, you can use |> with .NET methods only if you want to write all arguments on the left side of the operator. You can for example write:

("+", ["a"; "b"]) |> System.String.Join

... but that doesn't fit with the usual use of pipeline operator. When working with .NET API, it is usually better to use a C#-like style of programming (without pipelining), because pipeline works well only with functional libraries.

Upvotes: 89

Related Questions