2013-09-01 3 views
7

एफ # के साथ खेलना, मैं निम्नलिखित व्यवहार से उलझन में हूं।इस नौसिखिया उदाहरण में List.reduce क्यों आवश्यक है?

// 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 (>>) बाहर टिप्पणी की है, तो त्रुटि को

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

इस उदाहरण में http://fsharpforfunandprofit.com/posts/conciseness-functions-as-building-blocks/ से नीचे उबला हुआ है संकलक सब कुछ के साथ शांत हो जाएगा।

संपादित करें -> (इस वाक्य को अनदेखा करें, क्योंकि नीचे दिए गए उत्तर में मेरी समझ बदल गई है।): "एक तरफ, मुझे लगता है कि List.reduce (>>) सूची से अंतिम CoolLabel वापस कर देगा।"

धन्यवाद।

उत्तर

12

List.reduce (>>) के साथ लाइन को हटाने showRainbow के प्रकार को बदलता है और इसलिए आपको ऐसा कुछ मिलता है जो कोई फ़ंक्शन नहीं है और इसलिए पाइपलाइनिंग ऑपरेटर इसे defaultLabel के साथ तर्क के रूप में नहीं कह सकता है।

val showRainbow : (CoolLabel -> CoolLabel) list 
:

val showRainbow : (CoolLabel -> CoolLabel) 

आप लाइन निकालते हैं, तो आप कार्यों के एक सूची मिलती है:

मूल कार्यक्रम में, showRainbow के प्रकार के एक समारोह है कि दूसरे में एक CoolLabel बदल जाता है

यह उदाहरण एक छोटे से तरीके से कार्यों का उपयोग नहीं कर रहा है, इसलिए मुझे थोड़ा सा समझने की अनुमति दें। हम rainbow से शुरू करते हैं जो रंगों की एक सूची है। अगला, rainbow |> List.map setLabelरंग की सूची फ़ंक्शंस की सूची में बदल जाता है। आप के रूप में इस पढ़ सकते हैं:

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

लेकिन, setLabelदो तर्क लेता है। यहां हम केवल पहले निर्दिष्ट करते हैं, इसलिए परिणाम एक ऐसा कार्य है जो CoolLabel की अपेक्षा करता है और इंद्रधनुष के वर्तमान रंग में इसका रंग बदलता है।

एक बार आपके पास फ़ंक्शंस की सूची हो जाने के बाद, List.reduce (>>) उन्हें लिखता है - यह एक नया फ़ंक्शन बनाता है जो उन सभी को इनपुट पर प्राप्त करता है। यह पीला, आदि के लिए नारंगी लाल को defaultLabel का रंग बदल जाता है, तो, तो और अंत में इंडिगो के लिए -

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

अब आप देख सकते हैं क्यों इस बैंगनी के साथ एक लेबल देता है: तो परिणाम अनिवार्य रूप से एक समारोह है और फिर बैंगनी करने के लिए!

आप 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";} 
संबंधित मुद्दे