2013-07-01 6 views
6

मैं जावा के ओओ-सिस्टम (एक मजेदार परिप्रेक्ष्य) के बजाय ओकैम के मॉड्यूल सिस्टम का उपयोग करने के तरीके के बारे में एक ब्लॉग एंट्री लिख रहा हूं। मैं कुछ ऐसी चीज में आया हूं जो मुझे मजबूती के बारे में समझ में नहीं आता है। नीचे एक बेस मॉड्यूल और दो मॉड्यूल हैं जिनमें यह शामिल है:मॉड्यूल सहित,

module M = struct 
    type t = int 
    let make() = 1 
end 
module A = struct 
    include M 
end 
module B = struct 
    include M 
end 

अब एटी और बीटी एक ही प्रकार है! क्यूं कर? यह evidient यदि आप

let a = A.make();; 
let b = B.make();; 
[a;b] --> A.t list (* ? *) 

मैं जानता हूँ कि यह निजी प्रकार संक्षिप्त रूपों के साथ इस को रोकने के लिए, और फिर coercing का उपयोग करता है, तो आप उन्हें एक ही सूची में रखना चाहते हैं संभव है है। मेरा सवाल है: यह पहले से क्यों नहीं किया गया है? संकलक कैसे पता लगा सकता है कि A.t और B.t समान आधार प्रकार से आता है?

सादर
Olle

उत्तर

8

ऐसे कई मामले हैं जहां आप उन दो मॉड्यूल को संगत होना चाहते हैं। एक सरल उपयोग के मामले निम्नलिखित है:

module Hashtbl = struct ... (* definition in the stdlib *) end 

module ExtHashtbl = struct ... (* my own layer on top of it *) end 

मैं ExtHashtbl.tHashtbl.t के साथ संगत होना चाहते हैं, इसलिए है कि मैं कर सकते हैं कोड के बीच में ExtHashtbl के कार्यों Hashtbl.t का उपयोग कर, या मान जो किसी के द्वारा बनाया गया है पर संचालित करने के लिए अन्यथा केवल Hashtbl लाइब्रेरी के बारे में पता है, न कि मेरी खुद की सामग्री।

एमएल के सिद्धांत में मॉड्यूल एक ऑपरेशन के साथ जितना संभव हो उतना समीकरणों एक मॉड्यूल परिभाषा समृद्ध, उन्हें हस्ताक्षर में उजागर "मजबूत बनाने" कहा जाता है। विचार यह है कि यदि आप अधिक अमूर्तता (कम समीकरण) चाहते हैं, तो आप हमेशा इसे प्रतिबंधित करने के लिए एक प्रकार के हस्ताक्षर का उपयोग कर सकते हैं, इसलिए यह समीकरणों के लिए सख्ती से अधिक सामान्य है।

स्थिति मज़दूरों के मामले में थोड़ा अलग है। कि बजाय सरल मॉड्यूल के रूप ए और बी को परिभाषित करने के विचार करें, तो आप उन्हें खाली हस्ताक्षर पर functors बनाया था:

module A (U : sig end) = struct include M end 
module B (U : sig end) = struct include M end 

वहाँ तो, जो कि कहा जाता है "उत्पादक हैं एमएल मॉड्यूल प्रणालियों में functors के दो अलग विचार "(functor से प्रत्येक मंगलाचरण उत्पन्न करता है" फ्रेश "है कि अन्य आमंत्रण के साथ असंगत हैं प्रकार के), और लोगों को बुलाया" अनुप्रयोगी "(सभी बराबर तर्क पर functor के आमंत्रण संगत प्रकार)। OCaml प्रणाली एक अनुप्रयोगी तरह से बर्ताव करता है अगर आप इसे एक मॉड्यूल तर्क यह है कि (अधिक आम तौर पर एक पथ) नाम दिया गया है के साथ का दृष्टांत, और एक उत्पादक तरह से अगर आप इसे एक मॉड्यूल तर्क यह है कि अज्ञात है के साथ का दृष्टांत में।

आप जेवियर लेरोय के 2000 पेपर A Modular Module System (PDF) (वेबपृष्ठ A few papers on Caml से) में ओकैम मॉड्यूल सिस्टम के बारे में जानना चाहते हैं उससे कहीं ज्यादा सीख सकते हैं। ऊपर वर्णित सभी स्थितियों के लिए आपको नीचे दिए गए कोड उदाहरण भी मिलेंगे।

एमएल मॉड्यूल सिस्टम, विशेष रूप से Anreas Rossberg, डेरेक ड्रेयर और क्लाउडियो रूसो द्वारा पर हाल के काम, "अनुप्रयोगी" और "उत्पादक" functors के बीच क्लासिक भेद करने के लिए एक अलग दृष्टिकोण लाने के लिए एक प्रवृत्ति है। वे दावा करते हैं कि उन्हें "शुद्ध" और "अशुद्ध" मज़दूरों के अनुरूप होना चाहिए: मकसद जिनके आवेदन साइड इफेक्ट्स करते हैं, हमेशा जेनरेटिव होते हैं, जबकि मज़ेदार जो केवल शुद्ध शर्तों को लाते हैं उन्हें डिफ़ॉल्ट रूप से आवेदक होना चाहिए (इस तरह असंतुलन को मजबूर करने के लिए कुछ सीलिंग निर्माण के साथ, इस प्रकार अमूर्त प्रदान करना)।

module type S = sig 
    type t 
    val x : t 
end;; 

module M : S = struct 
    type t = int 
    let x = 1 
end;; 

(* definitions below are compatible, the test type-checks *) 
module A1 = M;; 
module B1 = M;; 
let _ = (A1.x = B1.x);; 

(* definitions below are each independently sealed with an abstract 
    signature, so incompatible; the test doesn't type-check *) 
module A2 : S = M;; 
module B2 : S = M;; 
let _ = (A2.x = B2.x);; 
(*This expression has type B2.t but an expression was expected of type A2.t*) 


(* note: if you don't seal Make with the S module type, all functor 
    applications will be transparently equal to M, and all examples below 
    then have compatible types. *) 
module Make (U : sig end) : S = M;; 

(* same functor applied to same argument: 
    compatible (applicative behavior) *) 
module U = struct end;; 
module A3 = Make(U);; 
module B3 = Make(U);; 
let _ = (A3.x = B3.x);; 

(* same functor applied to different argument: 
    incompatible (applicative behavior) *) 
module V = struct end;; 
module A4 = Make(U);; 
module B4 = Make(V);; 
let _ = (A4.x = B4.x);; 
(* This expression has type B4.t = Make(V).t 
    but an expression was expected of type A4.t = Make(U).t *) 

(* same functor applied to non-path (~unnamed) arguments: 
    incompatible (generative behavior) *) 
module A5 = Make(struct end);; 
module B5 = Make(struct end);; 
let _ = (A5.x = B5.x);; 
(* This expression has type B5.t but an expression was expected 
    of type A5.t *) 
4

मुझे समझ नहीं आता क्या पहले से ही नहीं किया जाता है, लेकिन:

  • शामिल में ocaml C में और एक # शामिल की तरह है, आप कक्षाएं उपयोग करना चाहते हैं और विरासत, फिर, वह सुविधा है: http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html
  • टाइप विरासत चलो ओकंपल अनुमान है कि() इकाई है -> टी। यदि आप ओकंपल को अनुमान लगाने के लिए नहीं चाहते हैं, तो आप फ़ंक्शन हस्ताक्षर को परिभाषित कर सकते हैं: http://caml.inria.fr/pub/docs/manual-ocaml/manual004.html#toc14
+0

धन्यवाद, लेकिन मेरा प्रश्न दार्शनिक प्रकृति से अधिक था। हो सकता है कि संकलक का अनुमान लगाएं कि यह वही प्रकार क्यों है क्योंकि यह कर सकता है, और संकलक हमेशा सबसे सामान्य प्रकार चाहता है। –

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