Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"

like image 688
bohdan_trotsenko Avatar asked Nov 25 '10 15:11

bohdan_trotsenko


2 Answers

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.

like image 104
Tomas Petricek Avatar answered Sep 17 '22 08:09

Tomas Petricek


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 "&" 
like image 24
Richiban Avatar answered Sep 17 '22 08:09

Richiban