2016-04-25 2 views
10

मेरे पास ओकैमल में कई कार्यक्रम लिखे गए हैं, उनमें से कुछ फ़ैक्टर का उपयोग करते हैं। अब, मैं एफ # में कोड के एक हिस्से को लिखने और फिर से लिखने पर विचार कर रहा हूं (ओकैम के पास कुछ फायदों का लाभ उठाने के लिए)। एक बात मुझे डर है कि ओकैमल में कौन से मज़ेदार काम करते हैं, एफ # में कोड लिखना है।OCaml में क्या फ़ैक्टर डॉक्टर करते हैं F # में कोड कैसे लिखें?

उदाहरण के लिए, हम एफ # में this example from OCaml manual का अनुकरण कैसे कर सकते हैं?

type comparison = Less | Equal | Greater 

module type ORDERED_TYPE = sig 
    type t 
    val compare: t -> t -> comparison 
end 

module Set = 
functor (Elt: ORDERED_TYPE) -> struct 
    type element = Elt.t 
    type set = element list 
    let empty = [] 
    let rec add x s = 
     match s with 
     [] -> [x] 
     | hd::tl -> 
     match Elt.compare x hd with 
      Equal -> s   (* x is already in s *) 
     | Less -> x :: s (* x is smaller than all elements of s *) 
     | Greater -> hd :: add x tl 
    end 

module OrderedString = struct 
    type t = string 
    let compare x y = if x = y then Equal else if x < y then Less else Greater 
end 

module OrderedInt = struct 
    type t = int 
    let compare x y = if x = y then Equal else if x < y then Less else Greater 
end 

module StringSet = Set(OrderedString) 
module IntSet = Set(OrderedInt) 

let try1() = StringSet.add "foo" StringSet.empty 
let try2() = IntSet.add 2 IntSet.empty 

उत्तर

6

जैसा कि आपने देखा, एफ # में मज़दूर नहीं हैं - एफ # मॉड्यूल प्रकारों द्वारा पैरामीटर नहीं किया जा सकता है। आप भाषा के ऑब्जेक्ट उन्मुख हिस्सों - इंटरफेस, सामान्य वर्ग और विरासत का उपयोग करके एफ # में समान परिणाम प्राप्त कर सकते हैं।

यहां आपके उदाहरण को अनुकरण करने के लिए एक भारी हाथ दृष्टिकोण है।

type Comparison = Less | Equal | Greater 

/// Interface corresponding to ORDERED_TYPE signature 
type IOrderedType<'a> = 
    abstract Value: 'a 
    abstract Compare: IOrderedType<'a> -> Comparison 

/// Type that implements ORDERED_TYPE signature, different instantiations 
/// of this type correspond to your OrderedInt/OrderedString modules. 
/// The 't: comparison constraint comes from the fact that (<) operator 
/// is used in the body of Compare. 
type Ordered<'t when 't: comparison> (t: 't) = 
    interface IOrderedType<'t> with 
     member this.Value = t 
     member this.Compare (other: IOrderedType<'t>) = 
      if t = other.Value then Equal else if t < other.Value then Less else Greater 

/// A generic type that works over instances of IOrderedType interface. 
type Set<'t, 'ot when 't: comparison and 'ot :> IOrderedType<'t>> (coll: IOrderedType<'t> list) = 

    member this.Values = 
     coll |> List.map (fun x -> x.Value) 

    member this.Add(x: 't) = 
     let rec add (x: IOrderedType<'t>) s = 
      match coll with 
      | [] -> [x] 
      | hd::tl -> 
       match x.Compare(hd) with 
       | Equal -> s   (* x is already in s *) 
       | Less -> x :: s (* x is smaller than all elements of s *) 
       | Greater -> hd :: add x tl 
     Set<'t, 'ot>(add (Ordered(x)) coll) 

    static member Empty = Set<'t, 'ot>(List.empty) 

/// A helper function for Set.Add. Useful in pipelines. 
module Set =  
    let add x (s: Set<_,_>) = 
     s.Add(x) 

/// Type aliases for different instantiations of Set 
/// (these could have easily been subtypes of Set as well) 
type StringSet = Set<string, Ordered<string>> 
type IntSet = Set<int, Ordered<int>> 

let try1() = Set.add "foo" StringSet.Empty 
let try2() = Set.add 2 IntSet.Empty 

try1().Values 
try2().Values 
+0

इस विस्तृत उत्तर के लिए धन्यवाद ... जब आप "भारी हाथ दृष्टिकोण" कहते हैं, तो आपका मतलब है कि अभ्यास में लोग इस तरह कोड नहीं करेंगे? – SoftTimur

+1

@ सॉफ़्ट टिमूर: क्रमबद्ध करें - मैंने मूल कोड से दूर नहीं जाने की कोशिश की, और जब तक मैं 'सेट' प्रकार के माध्यम से प्राप्त हुआ, तब तक यह मेरे लिए प्राकृतिक नहीं था। यह बहुत दूर नहीं है, लेकिन अगर मैंने क्लीन शीट से शुरू किया तो मैं कुछ अलग हो गया होगा। – scrwtp

+1

@ सॉफ़्ट टिमूर: हो सकता है कि यह 'सेट' पर केवल समेकित प्रकार पैरामीटर है। – scrwtp

6

यहां एक अलग दृष्टिकोण है जो एक सामान्य वर्ग और प्रति वस्तु एक वस्तु का उपयोग करके एक ही परिणाम प्राप्त करता है।

type Comparison = Less | Equal | Greater 

type Set<'a>(compare : 'a -> 'a -> Comparison) = 

    member this.Empty : 'a list = [] 

    member this.Add x s = 
     match s with 
     | [] -> [x] 
     | hd::tl -> 
      match compare x hd with 
      | Equal -> s   (* x is already in s *) 
      | Less -> x :: s (* x is smaller than all elements of s *) 
      | Greater -> hd :: this.Add x tl 


let compare x y = if x = y then Equal else if x < y then Less else Greater 

let compareFloats (x : float) (y : float) = if x = y then Equal else if x < y then Less else Greater 

// Note that same generic compare function can be used for stringSet and intSet 
// as long as the type parameter is explicitly given 
let stringSet = Set<string>(compare) 
let intSet = Set<int>(compare) 

// Type parameter not needed, because compareFloats is not generic 
let floatSet = Set(compareFloats) 

let try1() = stringSet.Add "foo" stringSet.Empty // -> ["foo"] 
let try2() = intSet.Add 2 intSet.Empty    // -> [2] 
let try3() = floatSet.Add 3.0 floatSet.Empty  // -> [3.0] 
+0

यही मेरा मतलब था जब मैंने अपना समाधान भारी हाथ कहा और प्राकृतिक महसूस नहीं किया। – scrwtp

+0

अगर मैं https://msdn.microsoft.com/en-us/library/dd412070(v=vs.110).aspx का उल्लेख करता हूं, तो मैं पूरी तरह से बंद हो जाऊंगा, और चुपचाप और सावधानी से जोड़ा गया: समाधान उपलब्ध होने पर कोड क्यों लिखें ? ;-) (हां मैं कर कर सीखने के लाभ को समझता हूं ...) –

+0

@ हेल्गेरनेउरोहोम सवाल यह था कि ओकैमल कोड को पोर्ट करने के लिए कैसे किया गया था जो फंक्शंस का उपयोग एफ # में करता है, सॉर्ट किए गए सेट को कैसे कार्यान्वित नहीं किया जाता है। मुझे आशा है कि यह उदाहरण यह पता लगाने में मदद करता है कि असली दुनिया के मामलों को एफ # में कैसे बंद करना है। – hvester

संबंधित मुद्दे