Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the pipe operator work?

Tags:

f#

If the pipe operator is created like this:

let (|>) f g = g f

And used like this:

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

Then what it seems to do is take List.Map and puts it behind (fun x -> x * x * x) And doesn't change anything about the position of [2;4;6]

So now it looks like this:

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

However this doesn't work.

I am just learning f# for the first time now. And this bothered me while reading a book about f#. So I might learn what I'm missing later but I decided to ask anyway.

It is obvious though that I am missing something major. Since I can easily recreate the pipe operator. But I don't get why it works. I might embarrass myself very soon as I learn more. Oh well.

like image 608
user1594138 Avatar asked Oct 16 '12 18:10

user1594138


People also ask

What does %>% operator do in R?

The pipe operator, written as %>% , has been a longstanding feature of the magrittr package for R. It takes the output of one function and passes it into another function as an argument. This allows us to link a sequence of analysis steps.

What is the pipe operator in Python?

What is the pipe operation? Pipe is a module in Python that easily connects the output from one method with the output from another method. It is a library that helps in writing cleaner code.

What is pipe operator in angular?

Use pipes to transform strings, currency amounts, dates, and other data for display. Pipes are simple functions to use in template expressions to accept an input value and return a transformed value. Pipes are useful because you can use them throughout your application, while only declaring each pipe once.

What is pipe () in JS?

A pipe is a function or operator that allows us to pass the output of a function as the input of another. JavaScript and TypeScript don't support pipes natively (as an operator), but we can implement our pipes using the following function: const pipe = <T>(... fns: Array<(arg: T) => T>) => (value: T) => fns.


2 Answers

The pipe operator is simply syntactic sugar for chained method calls. It's very similar to how linq expressions are expressed in C#.

Explanation from here:

Forward Pipe Operator I love this guy. The Forward pipe operator is simply defined as:

let (|>) x f = f x

And has a type signature:

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

Which translates to: given a generic type 'a, and a function which takes an 'a and returns a 'b, then return the application of the function on the input.

Rather than explaining this, let me give you 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 straight forward, but notice just how unruly the syntax looks. All we want to do is take the result of one computation and pass that to the next computation. We could rewrite it by introducing a series 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 those temporary variables straight. What the (|>) operator does is take a value, and 'forward it' to a function, essentially allowing you to specify the parameter of a function before the function call. This dramatically simplifies F# code by allowing you to pipe functions together, where the result of one is passed into the next. So to use the same example the code can be written clearly as:

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

Edit:

In F# what you're really doing with a method call is taking a function and then applying it to the parameter that follows, so in your example it would be List.map (fun x -> x * x * x) is applied to [2;4;6]. All that the pipe operator does is take the parameters in reverse order and then do the application reversing them back.

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

Standard F# call syntax: f g

Reversed F# call syntax: g f

Standard:

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

Reversed:

let var = [2;4;6] |> List.map (fun x -> x * x * x)
like image 183
N_A Avatar answered Oct 21 '22 23:10

N_A


The brackets around |> mean it is an infix operator so your example could 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 to

let result = (List.map (fun x -> x * x)) [2;4;6]
like image 34
Lee Avatar answered Oct 22 '22 00:10

Lee