ভাঁজ এবং হ্রাস মধ্যে পার্থক্য?


121

এফ # শেখার চেষ্টা করছেন তবে ভাঁজ এবং হ্রাসের মধ্যে পার্থক্য করার চেষ্টা করার সময় বিভ্রান্ত হয়ে পড়েন । ভাঁজ একই কাজ করে বলে মনে হচ্ছে তবে অতিরিক্ত প্যারামিটার লাগে। এই দুটি ফাংশন বিদ্যমান থাকার কোনও বৈধ কারণ আছে বা তারা সেখানে বিভিন্ন ব্যাকগ্রাউন্ডের লোকদের থাকার জন্য আছে? (উদাহরণস্বরূপ: সি # তে স্ট্রিং এবং স্ট্রিং)

নমুনা থেকে অনুলিপি কোড স্নিপেট এখানে:

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
@Neil - বাস্তবায়নকারী foldপরিপ্রেক্ষিতে এর reduceএর সঁচায়ক ধরণ - অধিক যে জটিল foldতালিকায় কিছু ধরণ হিসাবে একই হতে হবে না!
টমাস পেট্রিসেক

@ টমাস পেট্রিসেক আমার ভুল, আমি মূলত এটিকে অন্যভাবে লেখার ইচ্ছা নিয়েছিলাম।
নিল

উত্তর:


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হ্রাসের জন্য, সুতরাং ফলস্বরূপকে উপাদান টাইপের মতোই সীমাবদ্ধতা হ্রাস করুন। দেখুন টমাস Petricek এর উত্তর নিচে।
লি

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, সংগ্রহের ধরণ তালিকার মানগুলির ধরণের সমান is এর অর্থ হ'ল আপনার যদি সংখ্যার একটি তালিকা থাকে তবে ফলাফলটি একটি সংখ্যার হতে হবে। পূর্ববর্তী নমুনাটি প্রয়োগ করতে, আপনাকে stringপ্রথমে নম্বরগুলিতে রূপান্তর করতে হবে এবং তারপরে সংগ্রহ করতে হবে:

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

2
এমনটি হ্রাস করতে সংজ্ঞায়িত করুন যে এটি রানটাইমে ত্রুটি করতে পারে?
ফ্রেশিয়েবল

fold' & its ability to express কমানোর সাধারণতার উপর নোটের জন্য +1 । কিছু ভাষার স্ট্রাকচারাল চিরালিটির ধারণা রয়েছে (হাস্কেল আমি আপনাকে দেখছি) আপনি এই উইকিতে বাম বা ডানদিকের চাক্ষুষভাবে চিত্রিত করতে পারেন ( উইকে en.wikedia.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]), বা অ্যাপেন্ড অপারেটরের সাথে কনস প্রতিস্থাপন করবে। সুতরাং সংযোজন এই তালিকার সেরা উদাহরণ নয়।
জেপি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.