2013-09-01 39 views
7

玩弄F#,我很困惑以下行爲。當List.reduce (>>)被註釋掉,有來自http://fsharpforfunandprofit.com/posts/conciseness-functions-as-building-blocks/歸結在這個例子中,錯誤爲什麼在這個新手示例中需要List.reduce?

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

// 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 

List.reduce (>>)被刪除,我會認爲showRainbow應返回CoolLabel的列表,並編譯器對任何事情都會很酷。

編輯 - >(忽略這個句子,因爲下面的答案改變了我的理解。):「另外,我得到那個List.reduce(>>)將返回列表中的最後一個CoolLabel。」

謝謝。

回答

12

刪除行List.reduce (>>)更改showRainbow的類型,因此您得到的東西不是函數,因此流水線操作符不能用defaultLabel作爲參數調用它。

在原來的計劃中,showRainbow類型是變成一個CoolLabel到另一個功能:

val showRainbow : (CoolLabel -> CoolLabel) 

如果您刪除行,你得到的功能列表

val showRainbow : (CoolLabel -> CoolLabel) list 

這個例子不是用一個簡單的單向函數,所以讓我解釋一下什麼是實際上可以回事。我們從rainbow開始,這是一個顏色列表。接下來,rainbow |> List.map setLabel原來的顏色名單成功能列表。您可以閱讀爲:

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

但是,setLabel需要參數。這裏我們只指定第一個,所以結果是一個函數,預計CoolLabel並將其顏色更改爲彩虹的當前顏色。

一旦你擁有的功能列表,List.reduce (>>)組成他們 - 它建立調用所有的人都上它接收的輸入一個新的功能。所以結果基本上是一個函數:

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

現在你可以看到爲什麼這個返回與紫色標籤 - 它改變了defaultLabel紅的顏色,然後進行橙色,黃色等,最後到靛藍然後去紫羅蘭!

如果更改setLabel,以便它不會忽略原來的顏色,但也許它們合併(通過附加的字符串),然後你會看到setLabel功能是如何呼籲所有的顏色:

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

結果將是:

> defaultLabel |> showRainbow;; 
val it : CoolLabel = {label = " red orange yellow green blue indigo violet";} 
相關問題