एफ # करीबी समारोह

किसी के पास एक सभ्य उदाहरण है, अधिमानतः व्यावहारिक/उपयोगी, वे अवधारणा का प्रदर्शन पोस्ट कर सकते हैं?

0
ro fr bn

6 उत्तर

(संपादित करें: एक छोटा ओकंपल एफपी कोन चीजों को शुरू करने के लिए

     
    

करी का कोन (भोजन के बारे में एक कोन, जो भोजन के बारे में नहीं है)

         
      

एक छात्र जैक्स गैरीग में आया और कहा, "मुझे समझ में नहीं आता कि किस चीज के लिए अच्छा है।" जैक्स ने जवाब दिया, "मुझे अपना पसंदीदा भोजन और अपना पसंदीदा मिठाई बताएं"। परेशान छात्र ने जवाब दिया कि उन्हें ओकोनोमियाकी और कैंटन पसंद आया, लेकिन जब उनके पसंदीदा रेस्तरां ने ओकोनोमियाकी की सेवा की, तो उनके कंटन ने उन्हें अगली सुबह पेट में दर्द दिया। तो जैक्स ने छात्र को एक रेस्तरां में खाने के लिए लिया जो कि छात्र के पसंदीदा के रूप में अच्छी तरह से ओकोनोमियाकी की सेवा करता था, फिर उसे शहर भर में एक दुकान में ले गया जिसने उत्कृष्ट कंटन बनाया जहां छात्र खुशी से अपनी भूख को लागू करते थे। छात्र बैठे थे, लेकिन वह प्रबुद्ध नहीं था ... अगली सुबह जब वह जाग गया और उसका पेट ठीक लगा।

    
  

मेरे उदाहरण कोड का पुन: उपयोग और समावेशन के लिए इसका उपयोग करेंगे। एक बार जब आप इन्हें देखते हैं तो यह काफी स्पष्ट है और आपको एक ठोस, सरल उदाहरण देना चाहिए जिससे आप कई परिस्थितियों में आवेदन करने के बारे में सोच सकें।

हम एक पेड़ पर एक नक्शा करना चाहते हैं। इस फ़ंक्शन को प्रत्येक नोड पर घुमाया जा सकता है और लागू किया जा सकता है यदि उसे अधिक तर्क की आवश्यकता होती है - क्योंकि हम नोड पर एक को अंतिम तर्क के रूप में लागू करेंगे। इसे घुमाने की ज़रूरत नहीं है, लेकिन अन्य फ़ंक्शन लिखना (यह मानना ​​है कि यह फ़ंक्शन अन्य चरों के साथ अन्य मामलों में उपयोग किया जा रहा है) एक अपशिष्ट होगा।

type 'a tree = E of 'a | N of 'a * 'a tree * 'a tree
let rec tree_map f tree = match tree with
    | N(x,left,right) -> N(f x, tree_map f left, tree_map f right)
    | E(x) -> E(f x)

let sample_tree = N(1,E(3),E(4)
let multiply x y = x * y
let sample_tree2 = tree_map (multiply 3) sample_tree

लेकिन यह वही है जैसा:

let sample_tree2 = tree_map (fun x -> x * 3) sample_tree

तो यह सरल मामला विश्वास नहीं है। यह वास्तव में तब भी शक्तिशाली है जब आप भाषा का अधिक उपयोग करते हैं और स्वाभाविक रूप से इन परिस्थितियों में आते हैं। करीबी के रूप में कुछ कोड पुन: उपयोग के साथ दूसरा उदाहरण। एक प्राइम नंबर बनाने के लिए पुनरावृत्ति संबंध । वहां बहुत समानता है:

let rec f_recurrence f a seed n =
    match n with
    | a -> seed
    | _ -> let prev = f_recurrence f a seed (n-1) in
           prev + (f n prev)

let rowland = f_recurrence gcd 1 7
let cloitre = f_recurrence lcm 1 1

let rowland_prime n = (rowland (n+1)) - (rowland n)
let cloitre_prime n = ((cloitre (n+1))/(cloitre n)) - 1

ठीक है, अब पंक्तिभूमि और क्लॉइट्रे करीबी कार्य हैं, क्योंकि उनके पास मुफ्त चर हैं, और हम f_recurrence के बारे में जानने या चिंता किए बिना इसके अनुक्रम का कोई अनुक्रमणिका प्राप्त कर सकते हैं।

0
जोड़ा
यह उत्तर आंशिक फ़ंक्शन एप्लिकेशन का वर्णन करता है, जो करी से संबंधित है, लेकिन एक ही चीज़ नहीं है
जोड़ा लेखक phoog, स्रोत

यह एक काफी सरल प्रक्रिया है। एक समारोह लें, अपने तर्कों में से एक को बांधें और एक नया कार्य वापस करें। उदाहरण के लिए:

let concatStrings left right = left + right
let makeCommandPrompt= appendString "c:\> "

अब सरल concatStrings फ़ंक्शन को घुमाने के द्वारा, आप आसानी से किसी भी स्ट्रिंग के सामने एक डॉस शैली कमांड प्रॉम्प्ट जोड़ सकते हैं! वास्तव में उपयोगी!

ठीक है, वास्तव में नहीं। मुझे लगता है कि एक और उपयोगी मामला यह है कि जब मैं एक ऐसा फ़ंक्शन बनाना चाहता हूं जो मुझे स्ट्रीम में डेटा देता है।

let readDWORD array i = array[i] | array[i + 1] << 8 | array[i + 2] << 16 | 
    array[i + 3] << 24 //I've actually used this function in Python.

इसके बारे में सुविधाजनक हिस्सा यह है कि इस तरह की चीज के लिए एक पूरी कक्षा बनाने के बजाय, कन्स्ट्रक्टर को कॉल करना, obj.readDWORD() को कॉल करना, आपके पास सिर्फ एक ऐसा फ़ंक्शन है जिसे आप के नीचे से बाहर नहीं किया जा सकता है।

0
जोड़ा
यह उत्तर आंशिक फ़ंक्शन एप्लिकेशन का वर्णन करता है, जो करी से संबंधित है, लेकिन एक ही चीज़ नहीं है
जोड़ा लेखक phoog, स्रोत

पिछले उदाहरणों में सवाल का जवाब दिया गया था, जबकि एफ # प्रोग्रामिंग के लिए करीइंग लाभकारी कैसे हो सकता है, इसके दो सरल उदाहरण यहां दिए गए हैं।

open System.IO

let appendFile (fileName : string) (text : string) =
    let file = new StreamWriter(fileName, true)
    file.WriteLine(text)
    file.Close()

// Call it normally    
appendFile @"D:\Log.txt" "Processing Event X..."

// If you curry the function, you don't need to keep specifying the
// log file name.
let curriedAppendFile = appendFile @"D:\Log.txt"

// Adds data to "Log.txt"
curriedAppendFile "Processing Event Y..."

और भूलें कि आप फंक्शन के प्रिंटफ परिवार को करी कर सकते हैं! विवाहित संस्करण में, लैम्ब्डा की विशिष्ट कमी को ध्यान दें।

// Non curried, Prints 1 2 3 
List.iter (fun i -> printf "%d " i) [1 .. 3];;

// Curried, Prints 1 2 3
List.iter (printfn "%d ") [1 .. 3];;
0
जोड़ा
यह उत्तर आंशिक फ़ंक्शन एप्लिकेशन का वर्णन करता है, जो करी से संबंधित है, लेकिन एक ही चीज़ नहीं है
जोड़ा लेखक phoog, स्रोत

आप जानते हैं कि आप किसी सूची में फ़ंक्शन को मैप कर सकते हैं? उदाहरण के लिए, सूची के प्रत्येक तत्व में एक जोड़ने के लिए फ़ंक्शन मैप करना:

> List.map ((+) 1) [1; 2; 3];;
val it : int list = [2; 3; 4]

यह वास्तव में पहले से ही करीकरण का उपयोग कर रहा है क्योंकि (+) ऑपरेटर का उपयोग किसी तर्क को जोड़ने के लिए एक फ़ंक्शन बनाने के लिए किया गया था, लेकिन आप उसी फ़ंक्शन को मैप करने के लिए इसे बदलकर इस उदाहरण से थोड़ा अधिक निचोड़ सकते हैं सूचियों की सूची में से:

> List.map (List.map ((+) 1)) [[1; 2]; [3]];;
val it : int list = [[2; 3]; [4]]

करी के बिना आप इन कार्यों को आंशिक रूप से लागू नहीं कर सके और इसके बजाय कुछ लिखना होगा:

> List.map((fun xs -> List.map((fun n -> n + 1), xs)), [[1; 2]; [3]]);;
val it : int list = [[2; 3]; [4]]
0
जोड़ा
@phoog यह उत्तर सही ढंग से बताता है कि "करीब किए बिना आप इन कार्यों को आंशिक रूप से लागू नहीं कर सके"।
जोड़ा लेखक Jon Harrop, स्रोत
यह उत्तर आंशिक फ़ंक्शन एप्लिकेशन का वर्णन करता है, जो करी से संबंधित है, लेकिन एक ही चीज़ नहीं है
जोड़ा लेखक phoog, स्रोत

करीबी एक तर्क को एकल तर्क कार्यों की एक श्रृंखला में एकाधिक तर्कों के साथ बदलने की प्रक्रिया का वर्णन करता है। तीन-तर्क समारोह के लिए सी # में उदाहरण:

Func>> Curry(Func f)
{
    return a => b => c => f(a, b, c);
}

void UseACurriedFunction()
{
    var curryCompare = Curry(String.Compare);
    var a = "SomeString";
    var b = "SOMESTRING";
    Console.WriteLine(String.Compare(a, b, true));
    Console.WriteLine(curryCompare(a)(b)(true));

    //partial application
    var compareAWithB = curryCompare(a)(b);
    Console.WriteLine(compareAWithB(true));
    Console.WriteLine(compareAWithB(false));
}

अब, बूलियन तर्क शायद नहीं तर्क है जिसे आप आंशिक एप्लिकेशन के साथ खोलना चाहते हैं। यह एक कारण है कि एफ # कार्यों में तर्कों का क्रम पहले थोड़ा अजीब लग सकता है। आइए एक अलग सी # करी फ़ंक्शन को परिभाषित करें:

Func>> BackwardsCurry(Func f)
{
    return a => b => c => f(c, b, a);
}

अब, हम कुछ और अधिक उपयोगी कर सकते हैं:

void UseADifferentlyCurriedFunction()
{
    var curryCompare = BackwardsCurry(String.Compare);

    var caseSensitiveCompare = curryCompare(false);
    var caseInsensitiveCompare = curryCompare(true);

    var format = Curry(String.Format)("Results of comparing {0} with {1}:");

    var strings = new[] {"Hello", "HELLO", "Greetings", "GREETINGS"};

    foreach (var s in strings)
    {
        var caseSensitiveCompareWithS = caseSensitiveCompare(s);
        var caseInsensitiveCompareWithS = caseInsensitiveCompare(s);
        var formatWithS = format(s);

        foreach (var t in strings)
        {
            Console.WriteLine(formatWithS(t));
            Console.WriteLine(caseSensitiveCompareWithS(t));
            Console.WriteLine(caseInsensitiveCompareWithS(t));
        }
    }
}

सी # में इन उदाहरण क्यों हैं? क्योंकि एफ # में, फ़ंक्शन घोषणाएं डिफ़ॉल्ट रूप से curried हैं। आपको आमतौर पर कार्यों को करी करने की आवश्यकता नहीं होती है; वे पहले से ही चिंतित हैं। इसका मुख्य अपवाद फ्रेमवर्क विधियों और अन्य अधिभारित फ़ंक्शंस है, जो उनके एकाधिक तर्क वाले टुपल लेते हैं। इसलिए आप ऐसे कार्यों को करी करना चाहते हैं, और वास्तव में, मैं इस प्रश्न पर आया था जब मैं लाइब्रेरी फ़ंक्शन की तलाश में था जो ऐसा करेगा। मुझे लगता है कि यह गायब है (यदि वास्तव में यह है) क्योंकि यह लागू करने के लिए बहुत छोटा है:

let curry f a b c = f(a, b, c)

//overload resolution failure: there are two overloads with three arguments.
//let curryCompare = curry String.Compare

//This one might be more useful; it works because there's only one 3-argument overload
let backCurry f a b c = f(c, b, a)
let intParse = backCurry Int32.Parse
let intParseCurrentCultureAnyStyle = intParse CultureInfo.CurrentCulture NumberStyles.Any
let myInt = intParseCurrentCultureAnyStyle "23"
let myOtherInt = intParseCurrentCultureAnyStyle "42"

String.Compare के साथ विफलता के आसपास होने के लिए, जहां तक ​​मैं कह सकता हूं कि कौन सा 3-तर्क अधिभार चुनने का कोई तरीका नहीं है, आप एक गैर-सामान्य समाधान का उपयोग कर सकते हैं:

let curryCompare s1 s2 (b:bool) = String.Compare(s1, s2, b)
let backwardsCurryCompare (b:bool) s1 s2 = String.Compare(s1, s2, b)

मैं एफ # में आंशिक फ़ंक्शन एप्लिकेशन के उपयोग के बारे में विस्तार से नहीं जाऊंगा क्योंकि अन्य उत्तरों ने पहले से ही कवर किया है।

0
जोड़ा
यह स्वीकार्य उत्तर होना चाहिए
जोड़ा लेखक Sammy S., स्रोत

मैंने सी # मेरे ब्लॉग पर । यह बात यह है कि आप मौजूदा मल्टी-पैरामीटर फ़ंक्शन से बाहर एक पैरामीटर पर बंद एक फ़ंक्शन बना सकते हैं (मेरे उदाहरण में किसी दिए गए नगर पालिका के मूल्य पर बंद कर कर की गणना करने के लिए एक फ़ंक्शन बनाएं)।

कुक काउंटी में बिक्री कर की गणना के लिए विशेष रूप से एक अलग कार्य करने की बजाय यहां अपील की जा रही है, आप रनटाइम पर गतिशील रूप से फ़ंक्शन (और पुन: उपयोग) कर सकते हैं।

0
जोड़ा
+1, हालांकि आपका ब्लॉग लिंक टूटा हुआ प्रतीत होता है, मुझे संदेह है कि आपका उदाहरण सी # में वास्तविक फ़ंक्शन करीइंग दिखाता है, नकल नहीं। यह उत्तर केवल एकमात्र ऐसा है जो वास्तव में आंशिक फ़ंक्शन एप्लिकेशन के साथ भ्रमित करने के बजाय आंशिक फ़ंक्शन एप्लिकेशन को सक्षम करने वाली चीज़ के रूप में करीकरण का वर्णन करता है।
जोड़ा लेखक phoog, स्रोत
मैंने हाल ही में सामुदायिक सर्वर से साइटफिनिटी में अपना ब्लॉग माइग्रेट किया है। मुझे अपने पुराने ब्लॉग के डेटा को आयात करने के लिए एक उपयोगिता लिखने के लिए नहीं मिला है :( लेकिन मैंने करी को अनुकरण करने के लिए फ़ंक्शन ओवरलोडिंग का उपयोग किया। यदि आप दोनों पैरामीटर पास करते हैं, तो आप परिणाम प्राप्त करते हैं, यदि आप एक पास करते हैं, तो आपको एक func मिलता है जो लेता है दूसरा और परिणाम देता है। सच करी के रूप में सुरुचिपूर्ण नहीं है लेकिन यह काम करता है;)
जोड़ा लेखक Michael Brown, स्रोत