2017-11-13 15 views
7

मैं एक नंबर जोड़कर जब तक मैं एक ऐसा नाम है जो अभी तक नहीं है पाया द्वारा एक निर्देशिका का नाम खोजने की कोशिश कर रहा था के साथ filterM का उपयोग कैसे करें मौजूद हैं:एक अनंत सूची

head <$> filterM (fmap not . fexists_) [ getDatedDir t d n | n <- [0..] ] 

इस के साथ समस्या यह है कि कभी नहीं है रिटर्न। मुझे लगता है कि समस्या यह है कि हालांकि आईओ एक फंक्टर है, फिल्टरएम को सिर प्रभाव से पहले सभी आईओ करना है; यानी, यह प्रत्येक एन के लिए fexists का मूल्यांकन करना है - और यह निश्चित रूप से अनंत है।

अब, मैं इस का समाधान कर सकते हैं:

go t d 0 
where go t d n = do 
    let dir = getDatedDir t d n 
    fexists_ dir >>= \case 
     False -> return dir 
     True -> go t d (n+1) 

लेकिन मुझे लगता है कि वहाँ एक और अधिक सुरुचिपूर्ण दृष्टिकोण होने के लिए filterM या कुछ इसी तरह का उपयोग कर चाहिए।

यह एक सामान्य पर्याप्त पैटर्न की तरह लगता है कि शायद नियंत्रण में एक मौजूदा कार्य है। मोनाड, मैं इसे देख नहीं रहा हूं।

+1

आप 'होट' आईओ 'कार्यों की अनंत सूची को ध्वस्त करने के लिए' asum' का उपयोग कर सकते हैं और इस उत्तर में थोड़ा सा सफल होने वाला पहला प्राप्त कर सकते हैं: https://stackoverflow.com/questions/47120384/keeping- io-lazy-under-append/47126169 # 47126169 – danidiaz

+0

आलस्य और आईओ कभी-कभी अच्छी तरह से मिश्रण नहीं करते हैं। आप अपने आईओ ऑपरेशंस को आलसी में बदलने के लिए [System.IO.Lazy] (https://hackage.haskell.org/package/lazyio-0.1.0.4/docs/System-IO-Lazy.html) देख सकते हैं। – Redu

उत्तर

5

वहाँ Control.Monad.Loops से firstM है: एक सूची से

firstM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) 

वापसी पहले मूल्य, यदि कोई हो, यह देखते हुए विधेय को संतोषजनक।

+0

ऐसा लगता है कि मैं वास्तव में क्या कर रहा हूं। धन्यवाद! यह देखकर खुशी हुई कि मुझे नियंत्रण में कुछ याद नहीं आया था। मोनाद। – user3416536

2

मोनैड के बिना समकक्ष, find :: Foldable t => (a -> Bool) -> t a -> Maybe a होगा। लेकिन मुझे इसे मोनाड्स के साथ काम करने के लिए एक संस्करण नहीं मिल रहा है।

एक विचार findM खुद को लागू करने की हो सकती है:

import Data.Bool(bool) 

findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) 
findM f [] = return Nothing 
findM f (x:xs) = f x >>= bool (findM f xs) (return (Just x)) 

फिर आप इसे पसंद का उपयोग कर सकते हैं:

import System.Directory(doesFileExist) 

main = do 
    Just fln <- findM (not . doesDirectoryExist) (map (getDatedDir t d) [0..]) 
    putStrLn fln 

पहले फ़ाइल नाम ऐसा है कि फ़ाइल मौजूद नहीं है मुद्रित करने के लिए। बेशक आप fln को एक अलग तरीके से संसाधित भी कर सकते हैं।

+0

कुछ [समान रूप से टाइप किए गए मौजूदा कोड] हैं (https://hackage.haskell.org/package/llvm-hs-pure-5.1.0/docs/src/LLVM.Prelude.html#findM) लेकिन मानक नहीं है, यह ऐसा लगता है ... – ephemient

+0

@ephemient: वास्तव में। 'find' इस समस्या का सबसे नज़दीकी गैर-मोनड संस्करण था। लेकिन 'findM' मानक पैकेज में मौजूद नहीं प्रतीत होता है, न ही कोई होगल खोज किसी भी परिणाम उत्पन्न करता है। –

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