2012-01-25 16 views
18

में खंड 20.10.1.1 हास्केल 2010 भाषा रिपोर्ट कहा गया है कि:क्या कोई अच्छा कारण है कि 'deleteBy` का सबसे सामान्य प्रकार क्यों नहीं है?

deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a] 

वास्तव में, GHC library में कार्यान्वयन

deleteBy :: (b -> a -> Bool) -> b -> [a] -> [a] 

की अनुमति होगी, लेकिन वास्तव में के साथ पूर्व एक के लिए प्रकार को प्रतिबंधित करता है एनोटेशन।

इसलिए, एक उदाहरण के लिए नहीं कह सकता,:

क्योंकि
foo = deleteBy fsteq 42 [(43, "foo"), (44, "bar"), (42, "baz")] where 
    fsteq a (b,_) = a == b 

Int(Int, String) के रूप में ही नहीं है।

क्या इसके लिए कोई अच्छा कारण है?

कारण मैं पूछ रहा हूं कि, यदि इसके लिए कोई अच्छा कारण नहीं है, तो में Frege डेटा के बंदरगाह में अधिक सामान्य प्रकार के साथ शामिल होगा। सूची मैं वर्तमान में कर रहा हूं। लेकिन शायद मैं कुछ दिख रहा हूँ?

संपादित करें: जैसा कि @hammar ने बताया, यह अन्य xxx पर भी कार्य करता है।

उत्तर

11

Generalising deleteBy के प्रकार के एक बहुत ही व्यावहारिक तरीके से मानक का उल्लंघन करती है: पूरी तरह से वैध हास्केल कार्यक्रमों अमान्य हो, अनसुलझा अधिभार के लिए धन्यवाद।

यहाँ एक प्रदर्शन है:

class (Num a) => Magic a where 
    magic :: a -> Bool 

sameMagic :: (Magic a, Magic b) => a -> b -> Bool 
sameMagic a b = magic a == magic b 

test :: (Magic a) => [a] 
test = deleteBy sameMagic 42 [1234] 

हास्केल में, इस कार्यक्रम के पूरी तरह से अच्छी तरह से आपके द्वारा लिखा गया है, deleteBy का प्रतिबंधित प्रकार यह सुनिश्चित करता है कि 421234 के समान प्रकार की गारंटी है। सामान्यीकृत deleteBy के साथ, यह मामला नहीं है, और इसलिए 42 का प्रकार संदिग्ध है, जिससे प्रोग्राम अमान्य हो गया है। (यदि आप एक कम काल्पनिक उदाहरण चाहते हैं, एक समारोह जो toInteger के साथ दो Integral मूल्यों तुलना पर विचार करें।)

तो, शायद वहाँ इस प्रतिबंधित प्रकार (हालांकि अगर deleteBy सामान्यीकृत किया जा रहा है, मैं Hammar की पसंद करेंगे के लिए कोई अच्छा कारण है आपके प्रस्ताव के लिए संस्करण), लेकिन इसे सामान्यीकृत करना मानक का उल्लंघन करता है, और यह वैध प्रोग्राम तोड़ सकता है।

+1

यह उन अंतर्दृष्टिपूर्ण टिप्पणियों की तरह है जिन्हें मैं ढूंढ रहा था। मुझे कुछ सोचने के लिए देता है। – Ingo

+0

यह एक बहुत ही अंतर्दृष्टिपूर्ण जवाब है! – danr

+0

लेकिन टाइप-डिफॉल्टिंग नियमों द्वारा 42 को 'इंटीगर' तक हल नहीं किया जाना चाहिए? – haskelline

10

मुझे लगता है कि यह अन्य xxxBy फ़ंक्शंस के साथ समरूपता के लिए है। हालांकि, आपका प्रकार अभी भी अनिवार्य रूप से विशिष्ट है। मैं इसे पसंद करूंगा।

deleteBy :: (a -> Bool) -> [a] -> [a] 

फिर आप आंशिक आवेदन का उपयोग कर अपने उदाहरण लिख सकते हैं:

foo = deleteBy (fsteq 42) [(43, "foo"), (44, "bar"), (42, "baz")] where 
    fsteq a (b,_) = a == b 
+0

सिवाय इसके कि फ़िल्टर * सभी * बराबर तत्वों को हटा देगा, जहां हटाएं केवल पहले को हटाना होगा। – Ingo

+0

@ इंगो: ओह! आप बिल्कुल सही कह रहे है। 'फ़िल्टर' यहां नौकरी नहीं करेगा। – hammar

+1

निश्चित रूप से, इसके आस-पास के तरीके हैं, लेकिन आप देखते हैं, उद्देश्य मानक (हास्केल 2010, इस मामले में) से चिपकना है। सवाल यह है कि यदि यह थोड़ा अधिक सामान्य है तो यह मानक का उल्लंघन करता है। – Ingo

7

इंगो,

अपने मूल प्रश्न में

, यह आप पूछ रहे हैं क्यों हास्केल रिपोर्ट deleteBy निर्दिष्ट करता है इस तरह लगता है । इसलिए यदि कोई मजबूत कारण नहीं है, तो आप फ्रीज में एक अलग परिभाषा का उपयोग कर सकते हैं (जिसका अर्थ है कि आपको हास्केल रिपोर्ट अनुरूपता की परवाह नहीं है)।

Hammar कहते हैं, यह अन्य xxxBy कार्यों की तरह है: का उपयोग करता (==), deleteBy एक विधेय कि (==) की तरह है लेता है हटा दें: प्रकार (के एक -> एक - > बूल) और समकक्ष संबंध माना जाता है। जबकि टाइप सिस्टम यह जांच नहीं सकता है कि भविष्य वास्तव में एक समकक्ष संबंध है, यह फ़ंक्शन अनुबंध है। तो यह समझना बहुत आसान है कि xxxBy का मतलब क्या है यदि आप जानते हैं कि xxx का क्या अर्थ है। और हो सकता है कि यह हटाए जाने का मामला नहीं है, लेकिन कुछ मामलों में अनुमान के तहत एक कार्यान्वयन को अनुकूलित किया जा सकता है कि भविष्य में निर्दिष्ट गुण हैं (समकक्ष संबंध या कुल आदेश, आदि)।

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

तो यदि आप अधिक सामान्य कार्य चाहते हैं, तो क्यों न किसी अन्य कार्य को एक अलग नाम से परिभाषित करें? उदाहरण के लिए, हटाएं अगर हटाएं।

(मैं Hammar के जवाब पर टिप्पणी करना चाहता था, लेकिन मैं नहीं तो मैं इसे यहाँ लिखा जा सकता है।)

+0

राफेल, अच्छा आपने इसे उत्तर के रूप में लिखा है, इसलिए मैं इसे +1 कर सकता हूं। – Ingo

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