2013-03-23 7 views
8

dlist package में DList डेटा प्रकार है, जिसमें बहुत से उदाहरण हैं, लेकिन Foldable या Traversable नहीं हैं। मेरे दिमाग में, ये सबसे अधिक "सूची-जैसी" प्रकार कक्षाएं हैं। क्या कोई प्रदर्शन कारण है कि DList इन कक्षाओं का उदाहरण नहीं है?अंतर सूची क्यों फोल्ड करने योग्य नहीं है?

इसके अलावा, पैकेज foldr और unfoldr लागू करता है, लेकिन अन्य फ़ोल्डिंग फ़ंक्शंस में से कोई भी नहीं।

उत्तर

10

DList a एक newtype आवरण के आसपास [a] -> [a] है, जो एक contravariant स्थिति में एक a है, तो यह Foldable या Traversable, या यहाँ तक Functor सीधे लागू नहीं कर सकते। उन्हें लागू करने का एकमात्र तरीका नियमित सूचियों में और से परिवर्तित करना है (foldr कार्यान्वयन देखें), जो अंतर सूचियों के प्रदर्शन लाभ को हरा देता है।

+2

को Sjoerd का जवाब, एक डीएलआईस्ट ** निर्माण ** के लिए केवल कुशल है - यदि आपने अपनी सूची बनाई है और इसे संसाधित करना चाहते हैं, तो आपको इसे 'toList' के साथ गुप्त करना चाहिए और फिर नियमित सूची को संसाधित करना चाहिए। –

+4

तो हम बस 'फोल्ड (डीएल एफ) = गुना (एफ [])' क्यों परिभाषित नहीं करते हैं? हम इस बारे में भूल सकते हैं कि कैसे 'डीएलआईस्टी लागू किए जाते हैं और उन्हें तत्वों के अनुक्रम के कुछ प्रतिनिधित्व के रूप में देखते हैं, और फिर' फोल्डबल 'को लागू करने का अर्थ समझ में आता है। इस तरह 'फेंक्टर' और 'ट्रैवर्सबल' को लागू करने में शायद कुछ नुकसान होंगे, लेकिन 'फोल्डबल' काफी उचित लगता है। –

+2

हाँ, 'Foldable' बहुत खराब नहीं हो सकता है, पैकेज पहले से ही' foldr' है और यह सब के बाद पर्याप्त है। मुझे लगता है कि इसे लागू नहीं किया गया कारण है क्योंकि आखिरी अपडेट 200 9 में था, जब 'Foldable' अभी तक एक प्रसिद्ध प्रकार की श्रेणी नहीं थी। –

16

चर्च-एन्कोडेड सूचियों का उपयोग करने के लिए आपको DList के बजाय एक विकल्प पर विचार करना चाहिए। विचार यह है कि आप एक सूची को एक अपारदर्शी मान के रूप में दर्शाते हैं जो जानता है कि सूची में foldr निष्पादित करने के तरीके को कैसे। यह RankNTypes एक्सटेंशन का उपयोग कर की आवश्यकता है:

{-# LANGUAGE RankNTypes #-} 

import Prelude 
import Control.Applicative 
import Data.Foldable (Foldable) 
import qualified Data.Foldable as F 
import Data.Traversable (Traversable) 
import qualified Data.Traversable as T 

-- | Laws: 
-- 
-- > runList xs cons nil == xs 
-- > runList (fromList xs) f z == foldr f z xs 
-- > foldr f z (toList xs) == runList xs f z 
newtype ChurchList a = 
    ChurchList { runList :: forall r. (a -> r -> r) -> r -> r } 

-- | Make a 'ChurchList' out of a regular list. 
fromList :: [a] -> ChurchList a 
fromList xs = ChurchList $ \k z -> foldr k z xs 

-- | Turn a 'ChurchList' into a regular list. 
toList :: ChurchList a -> [a] 
toList xs = runList xs (:) [] 

-- | We can construct an empty 'ChurchList' without using a @[]@. 
nil :: ChurchList a 
nil = ChurchList $ \_ z -> z 

-- | The 'ChurchList' counterpart to '(:)'. Unlike 'DList', whose 
-- implementation uses the regular list type, 'ChurchList' doesn't 
-- rely on it at all. 
cons :: a -> ChurchList a -> ChurchList a 
cons x xs = ChurchList $ \k z -> k x (runList xs k z) 

-- | Append two 'ChurchList's. This runs in O(1) time. Note that 
-- there is no need to materialize the lists as @[a]@. 
append :: ChurchList a -> ChurchList a -> ChurchList a 
append xs ys = ChurchList $ \k z -> runList xs k (runList ys k z) 

-- | Map over a 'ChurchList'. No need to materialize the list. 
instance Functor ChurchList where 
    fmap f xs = ChurchList $ \k z -> runList xs (\x xs' -> k (f x) xs') z 

-- | The 'Foldable' instance is trivial, given the 'ChurchList' law. 
instance Foldable ChurchList where 
    foldr f z xs = runList xs f z 

instance Traversable ChurchList where 
    traverse f xs = runList xs step (pure nil) 
     where step x rest = cons <$> f x <*> rest 

इस के लिए नकारात्मक पक्ष यह एक ChurchList -folding एक ChurchList सस्ती है के लिए कोई कुशल tail आपरेशन वहाँ है, लेकिन बार-बार पूंछ लेने महंगा है कि है ...

इसके अलावा
+0

'चर्चलिस्ट' की 'पूंछ' की गणना लगातार, समय में, आलसी रूप से की जा सकती है। – is7s

+1

ध्यान दें कि मैंने कहा "बार-बार पूंछ लेना"; यदि आप सिर्फ एक बार पूंछ ले रहे हैं, तो सरल 'चर्च टेल = सूची से। पूंछ toList' बहुत बुरा नहीं लग रहा है। लेकिन अब विचार करें कि 'चर्चटेल' के साथ क्या होता है। चर्च टेल ': आपको एक' चर्च] 'द्वारा समर्थित' चर्च] 'प्राप्त होता है जिसे' चर्च सूची 'से बनाया गया है जो' [] '-list द्वारा समर्थित है। समस्या का दिल यह है कि 'चर्चलिस्ट' और इसकी 'चर्च टेल' संरचना को '[] '-list और इसकी पूंछ की तरह साझा नहीं करती है। मुझे विश्वास नहीं है कि 'चर्चटेल' के अधिक परिष्कृत कार्यान्वयन जो 'toList'/'से लिस्ट' का उपयोग नहीं करते हैं, इससे भी बच सकते हैं। –

+0

सच है, अन्य कार्यान्वयन के लिए भी 'पूंछ' दोहराया महंगा है। बीटीडब्ल्यू मुझे नहीं लगता कि 'चर्चलिस्ट' का 'परिशिष्ट' ऑपरेशन सामान्य सूची की तुलना में बेहतर है, है ना? – is7s

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

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