Why is List.reduce necessary in this example for beginners?

When playing with F #, I get confused with the following behavior. When List.reduce (>>) commented out, an error appears

 defaultLabel |> showRainbow ----------------^^^^^^^^^^^ This expression was expected to have type CoolLabel -> 'a but here has type (CoolLabel -> CoolLabel) list 

this example comes down to http://fsharpforfunandprofit.com/posts/conciseness-functions-as-building-blocks/ :

 // create an underlying type type CoolLabel = { label : string; } let defaultLabel = {label="";} let setLabel msg label = {label with CoolLabel.label = msg} let rainbow = ["red";"orange";"yellow";"green";"blue";"indigo";"violet"] let showRainbow = rainbow |> List.map setLabel |> List.reduce (>>) // test the showRainbow function defaultLabel |> showRainbow 

When List.reduce (>>) is deleted, I think showRainbow should return a CoolLabel list, and the compiler will be cool for everyone.

Change β†’ (Ignore this sentence because the answer below has changed my understanding.): β€œAside, I get List.reduce (β†’) to return the last CoolLabel from the list.”

Thanks.

+7
f #
source share
1 answer

Removing a string using List.reduce (>>) changes the type of showRainbow , and so you get what is not a function, and therefore the pipeline operator cannot call it defaultLabel as an argument.

In the source program, the showRainbow type is a function that turns one CoolLabel into another:

 val showRainbow : (CoolLabel -> CoolLabel) 

If you delete the line, you will get a list of functions:

 val showRainbow : (CoolLabel -> CoolLabel) list 

This example does not use functions trivially, so let me explain a little what is happening. Let's start with rainbow , which is a list of colors. Then rainbow |> List.map setLabel turns the list of colors into a list of functions. You can read this as:

 rainbow |> List.map (fun color -> setLabel color) 

But, setLabel takes two arguments. Here we indicate only the first, so the result is a function that expects CoolLabel and changes its color to the current rainbow color.

As soon as you have a list of functions, List.reduce (>>) compiles them - it creates a new function that calls all of them at the input it receives. Thus, the result is essentially a function:

 let resultingFunction input = setLabel "violet" (setLabel "indigo" (setLabel "blue" ( ... (input))))) 

Now you can understand why this returns a shortcut with a purple color - it changes the defaultLabel color to red, then to orange, then to yellow, etc. and finally on indigo and then on purple!

If you change setLabel so that it does not ignore the original color, but possibly combine them (by adding lines), then you will see how the setLabel function was called for all colors:

 let setLabel msg label = { label with CoolLabel.label = label.label + " " + msg } 

The result will be:

 > defaultLabel |> showRainbow;; val it : CoolLabel = {label = " red orange yellow green blue indigo violet";} 
+12
source share

All Articles