हम ListWithEnd
इस प्रकार परिभाषित कर सकते हैं:
import Control.Monad.Free
type LWE a e = Free ((,) a) e
हम आम तौर पर एक उम्मीद है कि अमूर्त या सामान्य अभ्यावेदन बॉयलरप्लेट की एक समग्र कमी के साथ हमें इनाम चाहिए । चलो देखते हैं कि यह प्रतिनिधित्व हमें क्या प्रदान करता है।
किसी भी मामले में, हम विपक्ष मामले के लिए एक पैटर्न पर्याय को परिभाषित करेगा:
{-# LANGUAGE PatternSynonyms #-}
pattern x :> xs = Free (x, xs)
infixr 5 :>
हम मैप कर सकते हैं गुना और अंत तत्व पर पार:
fmap (+1) (0 :> Pure 0) == (0 :> Pure 1)
traverse print (0 :> Pure 1) -- prints 1
Applicative
उदाहरण हमें देता है बहुत साफ संगतता:
xs = 1 :> 2 :> Pure 10
ys = 3 :> 4 :> Pure 20
xs *> ys == 1 :> 2 :> 3 :> 4 :> Pure 20 -- use right end
xs <* ys == 1 :> 2 :> 3 :> 4 :> Pure 10 -- use left end
(+) <$> xs <*> ys == 1 :> 2 :> 3 :> 4 :> Pure 30 -- combine ends
हम सूची elem पर नक्शा कर सकते हैं दस्तावेजों, अगर थोड़ा tortuously:
import Data.Bifunctor -- included in base-4.8!
hoistFree (first (+10)) xs == 11 :> 12 :> Pure 10
और हम iter
के उपयोग, निश्चित रूप से कर सकते हैं।
iter (uncurry (+)) (0 <$ xs) == 3 -- sum list elements
यह अच्छा होगा अगर LWE
हो सकता है एक Bitraversable
(और Bifunctor
और Bifoldable
), क्योंकि तब हम एक अधिक सामान्य और सैद्धांतिक रास्ते में सूची तत्वों का उपयोग कर सकते हैं। इसके लिए हमें निश्चित रूप से एक newtype की जरूरत है:
newtype LWE a e = LWE (Free ((,) a) e) deriving (lots of things)
instance Bifunctor LWE where bimap = bimapDefault
instance Bifoldable LWE where bifoldMap = bifoldMapDefault
instance Bitraversable LWE where bitraverse = ...
लेकिन इस बिंदु पर हम सिर्फ सादा एडीटी बाहर लेखन और कोड की लाइनों के एक जोड़े में Applicative
, Monad
और Bitraversable
उदाहरणों लिखने के बारे में सोच सकते हैं। वैकल्पिक रूप से, हम lens
का उपयोग करें और सूची तत्वों के लिए एक Traversal
लिख सकते हैं:
import Control.Lens
elems :: Traversal (LWE a e) (LWE b e) a b
elems f (Pure e) = pure (Pure e)
elems f (x :> xs) = (:>) <$> f x <*> elems f xs
इस रेखा के साथ आगे सोच रही थी, हम अंत तत्व के लिए एक Lens
बनाना चाहिए। यह जेनेरिक Free
इंटरफ़ेस पर बोनस का थोड़ा सा है, क्योंकि हम जानते हैं कि प्रत्येक परिमित LWE
में बिल्कुल एक अंत तत्व होना चाहिए, और हम इसके लिए Lens
(Traversal
या Prism
के बजाय) को स्पष्ट कर सकते हैं।
end :: Lens (LWE a e) (LWE a e') e e'
end f (Pure e) = Pure <$> f e
end f (x :> xs) = (x :>) <$> end f xs
मैंने इसे नहीं देखा है। शायद यह आसान होगा (पूर्वनिर्धारित कार्यों के साथ काम कर रहे wrt) 'newtype ListWithEnd e a = LWE ([a], e) को परिभाषित करने के लिए? –
@ थॉमसएम। डूबुइसन मुझे अंत में निर्माता में वास्तव में रहने की आवश्यकता है, क्योंकि मैं सूची बनाने के दौरान 'e' की गणना करने वाले कार्यों के साथ प्रयोग कर रहा हूं। –
मानक सामान के संदर्भ में इसे व्यक्त करने का प्रयास करते हुए, 'टाइप करें LWE e a = फ्री ((,) ए) ई' दिमाग में आता है। –