2012-08-23 7 views
5

"चेकसिंपल" आपको ब्रह्मांड यू का एक तत्व प्राप्त करता है, और (nat 1) को चेक किया गया है तो उसे दिए गए एग्डा प्रकार में परिवर्तित किया जा सकता है यू। रूपांतरण का परिणाम वापस कर दिया गया है।आगाडा: मेरा कोड चेक टाइप नहीं करता है (निहित तर्क कैसे प्राप्त करें?)

अब मैं एक कंसोल प्रोग्राम लिखने और कमांड लाइन से "someU" प्राप्त करने की कोशिश। पैरामीटर के रूप में (शायद कंसोल से इनपुट 'कुछ भी नहीं' हो सकता है क्योंकि):

इसलिए मैं एक (शायद यू यू) में शामिल करने के लिए "checkSimple" के प्रकार बदल दिया है। हालांकि मुझे कोड टाइप करने के लिए कोड नहीं मिल सकता है।

module CheckMain where 


open import Prelude 

-- Install Prelude 
---- clone this git repo: 
---- https://github.com/fkettelhoit/agda-prelude 

-- Configure Prelude 
--- press Meta/Alt and the letter X together 
--- type "customize-group" (i.e. in the mini buffer) 
--- type "agda2" 
--- expand the Entry "Agda2 Include Dirs:" 
--- add the directory 



data S : Set where 
    nat : (n : ℕ) → S 
    nil : S 

sToℕ : S → Maybe ℕ 
sToℕ (nat n) = just n 
sToℕ _  = nothing 


data U : Set where 
    nat  : U 

El : U → Set 
El nat = ℕ 


sToStat : (u : U) → S → Maybe (El u) 
sToStat nat   s = sToℕ s 


-- Basic Test 
test1 : Maybe ℕ 
test1 = sToStat nat (nat 1) 


{- THIS WORKS -} 

checkSimple : (u : U) → Maybe (El u) 
checkSimple someU = sToStat someU (nat 1) 



{- HERE IS THE ERROR -} 

-- in contrast to checkSimple we only get a (Maybe U) as a parameter 
-- (e.g. from console input) 

check : {u : U} (u1 : Maybe U) → Maybe (El u) 
check (just someU) = sToStat someU (nat 1) 
check _ = nothing 


{- HER IS THE ERROR MESSAGE -} 

{- 
someU != .u of type U 
when checking that the expression sToStat someU (nat 1) has type 
Maybe (El .u) 
-} 

उत्तर

8

मुद्दा प्रकृति में काफी सरल है: sToStat की जिसके परिणामस्वरूप प्रकार अपनी पहली तर्क (अपने कोड में u : U) के मूल्य पर निर्भर करता है; आप बाद में check अंदर sToStat का उपयोग करते हैं, तो आप वापसी प्रकार someU पर निर्भर रहना चाहते हैं - लेकिन check वादों अपनी वापसी प्रकार अंतर्निहित u : U बजाय पर निर्भर करता है कि!


अब, कल्पना करें कि यह टाइप चेक है, मैं आपको कुछ मुद्दों को उत्पन्न करूंगा।

क्या होगा अगर u1nothing है? खैर, उस मामले में हम nothing भी वापस करना चाहते हैं। किस प्रकार के nothing? Maybe (El u) आप कह सकते हैं, लेकिन यहाँ बात है - u एक अंतर्निहित तर्क, संकलक अन्य संदर्भ से हमारे लिए यह अनुमान लगाने के लिए कोशिश करेंगे जिसका मतलब है के रूप में चिह्नित किया गया है। लेकिन कोई अन्य संदर्भ नहीं है जो u के मान को पिन करेगा!

AGDA सबसे अधिक संभावना अनसुलझी metavariables के बारे में शिकायत जब भी आप check उपयोग करने के लिए, जिसका अर्थ है आप u का मूल्य लिखने के लिए हर जगह आप check उपयोग करते हैं, इस प्रकार u पहली जगह में निहित अंकन की बात को हराने के लिए है की कोशिश करेंगे। मामले में आप नहीं जानते थे, AGDA हमें अंतर्निहित तर्क प्रदान करने के लिए एक तरह से देता है:

check {u = nat} {- ... -} 

लेकिन मैं पीछे हटना। उदाहरण के लिए

data U : Set where 
    nat char : U 

: यदि आप और अधिक कंस्ट्रक्टर्स साथ U विस्तार

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

El : U → Set 
El nat = ℕ 
El char = Char 

अब, check {u = char} (just nat) क्या है? sToStat someU (nat 1)Maybe ℕ है, लेकिन El uChar है!


और अब संभावित समाधान के लिए। हमें check का परिणाम प्रकार u1 पर निर्भर करता है। अगर हम unJust समारोह किसी तरह का था, हम लिख सकता है

check : (u1 : Maybe U) → Maybe (El (unJust u1)) 

आपको तुरंत ही इस कोड के साथ समस्या को देखना चाहिए - कुछ भी नहीं हमें गारंटी देता है कि u1just है।भले ही हम nothing वापस लौट रहे हैं, हमें अभी भी एक सही प्रकार प्रदान करना होगा!

सबसे पहले, हमें nothing मामले के लिए कुछ प्रकार चुनने की आवश्यकता है। मान लें कि मैं बाद में U का विस्तार करना चाहता हूं, इसलिए मुझे कुछ तटस्थ चुनना होगा। Maybe ⊤ बहुत उचित लगता है (केवल एक त्वरित अनुस्मारक, () हैस्केल - इकाई प्रकार में है)।

हम कुछ मामलों में Maybe ℕ वापस कर सकते हैं और Maybe ⊤ दूसरों में? आह, हम एक समारोह का उपयोग कर सकते हैं!

Maybe-El : Maybe U → Set 
Maybe-El nothing = Maybe ⊤ 
Maybe-El (just u) = Maybe (El u) 

यही वही है जो हमें चाहिए! अब check बस हो जाता है:

check : (u : Maybe U) → Maybe-El u 
check (just someU) = sToStat someU (nat 1) 
check nothing  = nothing 

इसके अलावा, इस इन कार्यों के कमी व्यवहार उल्लेख करने के लिए सही अवसर है। Maybe-El उस संबंध में बहुत ही उपोष्णकटिबंधीय है, आइए एक और कार्यान्वयन देखें और तुलना करने की थोड़ी सी करें।

Maybe-El₂ : Maybe U → Set 
Maybe-El₂ = Maybe ∘ helper 
    where 
    helper : Maybe U → Set 
    helper nothing = ⊤ 
    helper (just u) = El u 

या शायद हम हमें कुछ टाइपिंग बचाने के लिए और लिख सकते हैं:

Maybe-El₂ : Maybe U → Set 
Maybe-El₂ = Maybe ∘ maybe El ⊤ 

ठीक है, पिछले Maybe-El और नए Maybe-El₂ अर्थ में बराबर कि वे एक ही इनपुट के लिए एक ही जवाब दे रहे हैं। वह है, ∀ x → Maybe-El x ≡ Maybe-El₂ x। लेकिन एक बड़ा अंतर है। क्या देखे बिना हम Maybe-El x के बारे में क्या बता सकते हैं? यह सही है, हम कुछ भी नहीं बता सकते हैं। जारी रखने से पहले दोनों फ़ंक्शन मामलों को x के बारे में कुछ जानने की आवश्यकता है।

लेकिन Maybe-El₂ के बारे में क्या? आइए इसे आजमाएं: हम Maybe-El₂ x से शुरू करते हैं, लेकिन इस बार, हम (केवल) फ़ंक्शन केस लागू कर सकते हैं। Unrolling कुछ परिभाषाओं, हम पर पहुंचने:

Maybe-El₂ x ⟶ (Maybe ∘ helper) x ⟶ Maybe (helper x) 

और अब हम अटक कर रहे हैं, क्योंकि helper x हम जानना चाहते हैं कि क्या x है की जरूरत को कम। लेकिन देखो, हमें Maybe-El के मुकाबले काफी दूर है। क्या इससे कोई फर्क पड़ता है?

यह बहुत ही मूर्खतापूर्ण समारोह पर विचार करें:

discard : {A : Set} → Maybe A → Maybe ⊤ 
discard _ = nothing 

स्वाभाविक रूप से, हम निम्नलिखित समारोह typecheck की उम्मीद करेंगे।

discard₂ : Maybe U → Maybe ⊤ 
discard₂ = discard ∘ check 

check, सही कुछ y के लिए Maybe y उत्पादन किया जाता है? आह, यहां समस्या आती है - हम जानते हैं कि check x : Maybe-El x, लेकिन हम x के बारे में कुछ भी नहीं जानते हैं, इसलिए हम Maybe-El x को Maybe y तक कम नहीं कर सकते हैं!

Maybe-El₂ पक्ष पर, स्थिति पूरी तरह से अलग है। हम जानते हैं कि Maybe-El₂ xMaybe y तक कम हो गया है, इसलिए discard₂ अब टाइपकेक!

+0

आपके उत्तर के लिए धन्यवाद।फिर, एक जबरदस्त प्रेरणा! – mrsteve

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