2010-08-29 12 views
11

में अपने बॉयलरप्लेट को स्क्रैप करें मैंने Scrap Your Boilerplate और हास्केल प्रोग्रामिंग भाषा में यूनिप्लेट लाइब्रेरी का उपयोग किया है, और मुझे लगता है कि भेदभाव वाले यूनियनों पर जेनेरिक प्रोग्रामिंग का यह रूप वास्तव में उपयोगी होगा। क्या एफ # प्रोग्रामिंग भाषा में समकक्ष लाइब्रेरी है?एफ #

उत्तर

11

मुझे पता नहीं है; भाषा/कंपाइलर में अंतर्निहित समर्थन के बिना, मुझे उम्मीद है कि एकमात्र विकल्प प्रतिबिंब-आधारित संस्करण है। (मुझे नहीं पता कि Uniplate लागू किया गया है - क्या आप?)

मूल प्रस्तुति के उदाहरण के आधार पर प्रतिबिंब-आधारित संस्करण के लिए कोड यहां दिया गया है। मैंने इसकी सीमाओं के बारे में गहराई से नहीं सोचा है, लेकिन यह अनुमान लगाने के मुकाबले लिखना बहुत आसान था।

type Company = C of Dept list 
and Dept = D of Name * Manager * SubUnit list 
and SubUnit = | PU of Employee | DU of Dept 
and Employee = E of Person * Salary 
and Person = P of Name * Address 
and Salary = S of float 
and Manager = Employee 
and Name = string 
and Address = string 

let data = C [D("Research",E(P("Fred","123 Rose"),S 10.0), 
        [PU(E(P("Bill","15 Oak"),S 5.0))])] 
printfn "%A" data 

open Microsoft.FSharp.Reflection 
let everywhere<'a,'b>(f:'a->'a, src:'b) = // ' 
    let ft = typeof<'a>    // ' 
    let rec traverse (o:obj) = 
     let ot = o.GetType() 
     if ft = ot then 
      f (o :?> 'a) |> box // ' 
     elif FSharpType.IsUnion(ot) then 
      let info,vals = FSharpValue.GetUnionFields(o, ot) 
      FSharpValue.MakeUnion(info, vals |> Array.map traverse) 
     else 
      o 
    traverse src :?> 'b  // ' 

let incS (S x) = S(x+1.0) 

let newData = everywhere(incS, data) 
printfn "%A" newData 

everywhere समारोह एक मनमाना ड्यू की पूरी संरचना को पार करता है और प्रत्येक नोड है कि प्रकार है कि f पर काम करता है, अन्य सभी नोड्स छोड़ने के रूप में-है करने के लिए समारोह f लागू होता है।

+0

यह एक अच्छा सुझाव है, मुझे इस तरह के दृष्टिकोण के प्रदर्शन के प्रभावों के बारे में सोचना होगा। यह शायद मेरे विशेष उपयोगकेस के लिए कोई फर्क नहीं पड़ता। –

+0

पुन: स्रोत के कार्यान्वयन के बारे में आपका प्रश्न http://community.haskell.org/~ndm/darcs/uniplate/ पर उपलब्ध है। –

+0

मैंने आपका जवाब स्वीकार कर लिया है क्योंकि मुझे लगता है कि यह एक अच्छा दृष्टिकोण है - लेकिन मैं इसे सही तरीके से काम करने के लिए एक बदलाव करता हूं: मैंने 'ot.IsSubclassOf (ft)' के साथ 'ft = ot' को प्रतिस्थापित किया - अन्यथा यह मिलान के विफल होने पर विफल रहता है, यानी 'एक विशिष्ट तर्क पारित होने से अधिक सामान्य है। –