मैं वास्तव में एक सामान्य तरीके से catamorphisms/anamorphisms साथ काम करने का विचार की तरह है, लेकिन यह मेरे लिए एक महत्वपूर्ण प्रदर्शन दोष यह है लगता है:यह इस तरह के रूप में catamorphisms GHC अनुकूलन (डीफॉरेस्ट) सामान्य कार्यों बनाने के लिए संभव है?
मान लीजिए हम स्पष्ट रास्ते में एक वृक्ष संरचना के साथ काम करना चाहते हैं - वर्णन करने के लिए विभिन्न तह का उपयोग कर एक सामान्य catamorphism function:
newtype Fix f = Fix { unfix :: f (Fix f) }
data TreeT r = Leaf | Tree r r
instance Functor TreeT where
fmap f Leaf = Leaf
fmap f (Tree l r) = Tree (f l) (f r)
type Tree = Fix TreeT
catam :: (Functor f) => (f a -> a) -> (Fix f -> a)
catam f = f . fmap (catam f) . unfix
अब हम जैसे कार्यों लिख सकते हैं:
depth1 :: Tree -> Int
depth1 = catam g
where
g Leaf = 0
g (Tree l r) = max l r
दुर्भाग्य से, इस दृष्टिकोण एक महत्वपूर्ण दोष यह है: Dur गणना ing, TreeT Int
के नए उदाहरणों सिर्फ तुरंत g
से भस्म किया जाना fmap
में हर स्तर पर बनाया जाता है। शास्त्रीय परिभाषा
depth2 :: Tree -> Int
depth2 (Fix Leaf) = 0
depth2 (Fix (Tree l r)) = max (depth1 l) (depth1 r)
की तुलना में हमारे depth1
हमेशा धीमी जीसी पर अनावश्यक तनाव बना रही हो जाएगा। एक समाधान hylomorphisms का उपयोग करना होगा और एक साथ सृजन और तह पेड़ को जोड़ना होगा। लेकिन अक्सर हम देखते हैं कि, हम चाहते हो सकता है एक पेड़ एक ही स्थान पर पर बनाया जाना है और फिर कहीं और से पारित कर दिया बाद में तह किया जा करने के लिए नहीं करना चाहती। या, विभिन्न catamorphisms के साथ कई बार फ़ोल्डर होने के लिए।
वहाँ GHC अनुकूलन depth1
बनाने के लिए एक तरीका है? catam g
और फिर fusing/deforestingg . fmap ...
अंदर इनलाइन करने की तरह कुछ?
मुझे इस पार्टी के लिए देर हो चुकी है, लेकिन पेड़ की गहराई की गणना करने के लिए फ़ंक्शन के लिए 'g' (या' deep2') के 'वृक्ष' मामले में कहीं भी '+ 1' नहीं होना चाहिए? अन्यथा, मैं नहीं देख सकता कि कैसे गहराई 1' या 'गहराई 2 कुछ भी वापस कर सकता है लेकिन शून्य। –
इसके अलावा, मुझे लगता है कि 'गहराई 1' वास्तव में' गहराई 2' की परिभाषा में 'गहराई 2' होना चाहिए। –