गुना और कम के बीच अंतर?


121

एफ # सीखने की कोशिश कर रहा है, लेकिन गुना और कम के बीच अंतर करने की कोशिश करते समय भ्रमित हो गया । गुना एक ही काम करने लगता है, लेकिन एक अतिरिक्त पैरामीटर लेता है। क्या इन दोनों कार्यों के मौजूद होने का कोई वैध कारण है या वे अलग-अलग पृष्ठभूमि वाले लोगों को समायोजित करने के लिए हैं? (जैसे: स्ट्रिंग और स्ट्रिंग # C में)

यहाँ कोड स्निपेट नमूना से कॉपी किया गया है:

let sumAList list =
    List.reduce (fun acc elem -> acc + elem) list

let sumAFoldingList list =
    List.fold (fun acc elem -> acc + elem) 0 list

printfn "Are these two the same? %A " 
             (sumAList [2; 4; 10] = sumAFoldingList [2; 4; 10])

1
आप एक दूसरे के संदर्भ में कम और गुना लिख ​​सकते हैं, जैसे fold f a lलिखा जा सकता है reduce f a::l
नील

9
@ नील - के foldसंदर्भ में लागू करने की reduceतुलना में अधिक जटिल है - foldसूची में चीजों के प्रकार के समान संचायक का प्रकार नहीं होना चाहिए!
टॉमस पेट्रीक

@TomasPetricek मेरी गलती, मैं मूल रूप से इसे दूसरे तरीके से लिखने का इरादा रखता था।
नील

जवाबों:


171

Foldसंचायक के लिए एक स्पष्ट प्रारंभिक मूल्य लेता है, जबकि reduceप्रारंभिक संचयकर्ता मूल्य के रूप में इनपुट सूची के पहले तत्व का उपयोग करता है।

इसका मतलब है कि संचायक और इसलिए परिणाम प्रकार को सूची तत्व प्रकार से मेल खाना चाहिए, जबकि वे अलग हो सकते हैं foldक्योंकि संचायक अलग से प्रदान किया जाता है। यह प्रकारों में परिलक्षित होता है:

List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
List.reduce : ('T -> 'T -> 'T) -> 'T list -> 'T

इसके अलावा reduceएक खाली इनपुट सूची पर एक अपवाद फेंकता है।


तो मूल रूप से करने के बजाय fold, आप बस सूची के आरंभ में उस प्रारंभिक मूल्य को जोड़ सकते हैं और कर सकते हैं reduce? foldतब की बात क्या है ?
पचेरियर

2
@ स्पेसर - फोल्ड के लिए संचायक फ़ंक्शन का एक अलग प्रकार है: 'state -> 'a -> 'stateगुना बनाम 'a -> 'a -> 'aकम करने के लिए, इसलिए कमी को कम करें परिणाम प्रकार तत्व प्रकार के समान होना चाहिए। नीचे देखें टॉमस पेट्रीक का जवाब
ली

178

क्या ली ने कहा कि इसके अलावा, आप को परिभाषित कर सकते reduceकरने के मामले में fold, लेकिन नहीं (आसानी से) इसका उल्टा:

let reduce f list = 
  match list with
  | head::tail -> List.fold f head tail
  | [] -> failwith "The list was empty!"

foldसंचायक के लिए एक स्पष्ट प्रारंभिक मूल्य लेने वाले तथ्य का अर्थ यह भी है कि foldफ़ंक्शन का परिणाम सूची में मानों के प्रकार से भिन्न प्रकार हो सकता है। उदाहरण के लिए, आप stringसूची में सभी संख्याओं को एक पाठीय प्रतिनिधित्व में संक्षिप्त करने के लिए प्रकार के संचायक का उपयोग कर सकते हैं :

[1 .. 10] |> List.fold (fun str n -> str + "," + (string n)) ""

उपयोग करते समय reduce, संचायक का प्रकार सूची में मानों के प्रकार के समान होता है - इसका मतलब है कि यदि आपके पास संख्याओं की सूची है, तो परिणाम को एक संख्या होना होगा। पिछले नमूने को लागू करने के लिए, आपको संख्याओं को stringपहले बदलना होगा और फिर जमा करना होगा:

[1 .. 10] |> List.map string
          |> List.reduce (fun s1 s2 -> s1 + "," + s2)

2
क्यों परिभाषित कम करें कि यह रनटाइम में त्रुटि कर सकता है?
Fresheyeball

fold' & its ability to express कम करने की व्यापकता पर ध्यान दें के लिए +1 । ' कुछ भाषाओं में स्ट्रक्चरल चिरलिटी (हास्केल मैं आपको देख रहा हूं) की अवधारणा है, आप इस विकी ( en.wikipedia.org/wiki/Fold_%28higher-order_function ) में बाएं या दाएं नेत्रहीन रूप से चित्रित कर सकते हैं । एक पहचान निर्माण के साथ, अन्य दो 'मौलिक' एफपी ऑपरेटर (फ़िल्टर और फ़ैप) भी एक मौजूदा `गुना 'प्रथम श्रेणी के भाषा निर्माण (वे सभी समसामयिक निर्माण हैं) के साथ लागू करने योग्य हैं। ( cs.nott.ac.uk/~pszgmh/fold.pdf ) देखें: HoTT, प्रिंसटन (यह टिप्पणी अनुभाग शामिल करने के लिए बहुत छोटा है ..)
एंड्रयू

जिज्ञासा से बाहर .. क्या यह गुना से प्रदर्शन को कम कर देगा क्योंकि यह प्रकार और अपवादों के बारे में कम मान्यताओं के तहत है?
sksallaj

19

आइए उनके हस्ताक्षर देखें:

> List.reduce;;
val it : (('a -> 'a -> 'a) -> 'a list -> 'a) = <fun:clo@1>
> List.fold;;
val it : (('a -> 'b -> 'a) -> 'a -> 'b list -> 'a) = <fun:clo@2-1>

कुछ महत्वपूर्ण अंतर हैं:

  • reduceकेवल एक प्रकार के तत्वों पर काम करते समय , संचायक और सूची तत्व foldविभिन्न प्रकारों में हो सकते हैं।
  • इसके साथ reduce, आप fपहले से शुरू होने वाले प्रत्येक सूची तत्व के लिए एक फ़ंक्शन लागू करते हैं :

    f (... (f i0 i1) i2 ...) iN

    इसके साथ fold, आप fसंचायक से शुरू होने वाले आवेदन s:

    f (... (f s i0) i1 ...) iN

इसलिए, रिक्त सूची पर reduceपरिणाम ArgumentException। इसके अलावा, foldकी तुलना में अधिक सामान्य है reduce; आप आसानी foldसे लागू करने के लिए उपयोग कर सकते reduceहैं।

कुछ मामलों में, उपयोग reduceकरना अधिक रसीला है:

// Return the last element in the list
let last xs = List.reduce (fun _ x -> x) xs

या अधिक सुविधाजनक अगर कोई उचित संचायक नहीं है:

// Intersect a list of sets altogether
let intersectMany xss = List.reduce (fun acc xs -> Set.intersect acc xs) xss

सामान्य तौर पर, foldएक मनमाने प्रकार के संचायक के साथ अधिक शक्तिशाली होता है:

// Reverse a list using an empty list as the accumulator
let rev xs = List.fold (fun acc x -> x::acc) [] xs

18

foldकी तुलना में अधिक मूल्यवान कार्य है reduce। आप के संदर्भ में कई विभिन्न कार्यों को परिभाषित कर सकते हैं fold

reduceका एक सबसेट है fold

गुना की परिभाषा:

let rec fold f v xs =
    match xs with 
    | [] -> v
    | (x::xs) -> f (x) (fold f v xs )

गुना के संदर्भ में परिभाषित कार्यों के उदाहरण:

let sum xs = fold (fun x y -> x + y) 0 xs

let product xs = fold (fun x y -> x * y) 1 xs

let length xs = fold (fun _ y -> 1 + y) 0 xs

let all p xs = fold (fun x y -> (p x) && y) true xs

let reverse xs = fold (fun x y -> y @ [x]) [] xs

let map f xs = fold (fun x y -> f x :: y) [] xs

let append xs ys = fold (fun x y -> x :: y) [] [xs;ys]

let any p xs = fold (fun x y -> (p x) || y) false xs 

let filter p xs = 
    let func x y =
        match (p x) with
        | true -> x::y
        | _ -> y
    fold func [] xs

1
आप अपने को परिभाषित foldअलग ढंग से List.foldके प्रकार के रूप में List.foldहै ('a -> 'b -> 'a) -> 'a -> 'b list -> 'aअपने मामले है, लेकिन में ('a -> 'b -> 'b) -> 'b -> 'a list -> 'b। बस इसे स्पष्ट करने के लिए। इसके अलावा, अपेंडेंस का आपका कार्यान्वयन गलत है। यदि आप इसे करने के लिए एक बाँध जोड़ते हैं तो यह काम करेगा, जैसे List.collect id (fold (fun x y -> x :: y) [] [xs;ys]), या परिशिष्ट ऑपरेटर के साथ विपक्ष को बदलें। इस प्रकार इस सूची में परिशिष्ट सबसे अच्छा उदाहरण नहीं है।
जेपी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.