Why does the pipe operator work?

If the pipe operator is created as follows:

let (|>) fg = gf 

And used like this:

 let result = [2;4;6] |> List.map (fun x -> x * x * x) 

Then what it seems to him is to take List.Map and place it (fun x → x * x * x) And nothing changes the position [2; 4; 6]

So now it looks like this:

 let result2 = [2;4;6] (fun x -> x * x * x) List.map 

However, this does not work.

I am just learning f # for the first time. And that bothered me while reading a book about f #. So I could find out what I was missing later, but I decided to ask anyway.

Obviously, I am missing something serious. Since I can easily recreate the pipe operator. But I do not understand why this works. I will be very embarrassed when I learn more. Oh good.

+8
f #
source share
4 answers

The pipe operator is just syntactic sugar for chain calls. This is very similar to how linq expressions are expressed in C #.

Explanation from here :

Straight pipe operator I love this guy. The straight pipe operator is simply defined as:

 let (|>) xf = fx 

And it has a signature like:

 'a -> ('a -> 'b) -> 'b 

Which means: a given generic type 'a and a function that takes' a and returns a' b, then returns the application of the function to the input.

Instead of explaining this, let me give an example of where it can be used:

 // Take a number, square it, then convert it to a string, then reverse that string let square x = x * x let toStr (x : int) = x.ToString() let rev (x : string) = new String(Array.rev (x.ToCharArray())) // 512 -> 1024 -> "1024" -> "4201" let result = rev (toStr (square 512)) 

The code is very simple, but note how disobedient the syntax looks. All we want to do is take the result of one calculation and pass it on to the next calculation. We could rewrite it by introducing a number of new variables:

 let step1 = square 512 let step2 = toStr step1 let step3 = rev step2 let result = step3 

But now you need to keep all these temporary variables straight. What the operator (|>) does is take a value and "redirect it" to the function, essentially letting you specify a function parameter before calling the function. This greatly simplifies the F # code, allowing you to combine functions together when the result of one is passed to the next. Therefore, to use the same example, the code can be written clearly:

 let result = 512 |> square |> toStr |> rev 

Edit

In F #, what you really do with the method call takes a function and then applies it to the next parameter, so in your example, this will be List.map (fun x -> x * x * x) applied to [2;4;6] . Everything the pipe operator does takes the parameters in the reverse order, and then the application reverses them.

Function

: List.map (fun x -> x * x * x) parameter: [2;4;6]

Standard F # Call Syntax: fg

Inverse F # Call Syntax: gf

Standard:

 let var = List.map (fun x -> x * x * x) [2;4;6] 

Inverted:

 let var = [2;4;6] |> List.map (fun x -> x * x * x) 
+11
source share

The brackets around |> mean that this is an infix operator, so your example can be written

 let result = (|>) [2;4;6] (List.map (fun x -> x * x * x)) 

Since |> applies its first argument to the second, this is equivalent

 let result = (List.map (fun x -> x * x)) [2;4;6] 
+8
source share

As mentioned above, basically you do not understand what result will be resolved. That would really solve

List.map (fun x -> x * x * x) [2;4;6]

List.map takes two arguments: a function that applies to all elements in the list and list. (fun x -> x * x * x) is the first argument, and [2;4;6] is the second.

Basically, just put what is to the left of |> , after what is to the right.

+5
source share

If you enter your definition of |> in fsi and look at the signature of the operator obtained by type, you will notice val ( |> ) : 'a -> ('a -> 'b) -> 'b , that is, the argument 'a , given function ('a -> 'b) , gives 'b .

Now create this signature in your expression [2;4;6] |> List.map (fun x -> x * x * x) , and you will get List.map (fun x -> x * x * x) [2;4;6] , where the argument is a list [2;4;6] , and the function partially uses the function of a single argument List.map (fun x -> x * x * x) .

+3
source share

All Articles