5

मैं एक समारोह जो एक सूची के तत्वों पर एक विधेय परीक्षण रहा हूँ, प्रत्येक तत्व जो विधेय संतुष्ट करता है और केवल उस तत्व को एक समारोह के लिए लागू होता है के लिए एक नई सूची बनाता है।कैसे मुहावरे इस समारोह में लिखने के लिए?

उदाहरण:

someFunction :: (a -> Bool) -> (a -> a) -> [a] -> [[a]] 
someFunction = ... 

let ys = someFunction isOdd (* 2) [1..10] 
    {- ys == [[2, 2, 3, 4, 5, ...], 
       [1, 2, 6, 4, 5, ...], 
       [1, 2, 3, 4, 10, ...], 
       ...] -} 

ys में, पहली सूची, मूल एक के बराबर है पहला तत्व है, जो विधेय संतुष्ट करता है और 2 से गुणा किया जाता छोड़कर। दूसरी सूची भी मूल एक के बराबर, तीसरा तत्व को छोड़कर इतने पर है, और।

मैं मान जो विधेय को संतुष्ट और उसके बाद सूचकांक के माध्यम से मानचित्रण के सूचकांकों लेने के द्वारा इस तरह के एक समारोह में लिखने के लिए सक्षम है। बहरहाल, यह बहुत कार्यात्मक प्रतीत नहीं होता और मैं एक अधिक मुहावरेदार दृष्टिकोण देखना चाहेंगे।

उत्तर

4

आप अपने समारोह लागू करें आप प्रत्येक आइटम पर अपनी अंगुली को डी:: की तरह एक zipper एक उंगली (उपयोग कर सकते हैं डी जब आप पढ़ सकते हैं के रूप में)

someFunction :: (a -> Bool) -> (a -> a) -> [a] -> [[a]] 
someFunction check f xs = r [] xs 
    where r _ []  = [] 
     r ps (y:ys) = let rs = r (ps ++ [y]) ys 
         in if check y then [ps ++ [f y] ++ ys] ++ rs 
            else rs 

r समारोह ps "संसाधित तत्वों" और (y:ys) "लंबित तत्वों" ले लो।

यदि आपको रैखिक लागत की आवश्यकता है (ps ++ [y] ऑपरेशन इसे cuadratic करते हैं) कुशल पूंछ सम्मिलन संरचना का उपयोग करें।

का उपयोग splitAt आप

someFunction check f xs = map (\(a,(x:b)) -> a ++ [f x] ++ b) $ 
          filter (check.head.snd) 
          [splitAt n xs | n <- [0..length xs - 1]] 

लिख सकते हैं या इसका उपयोग करते सूची समझ

someFunction check f xs = 
    [ a ++ [f x] ++ b | n <- [0..length xs - 1] 
         , let (a, (x:b)) = splitAt n xs 
         , check x] 

zip @chi समाधान द्वारा सुझाए गए का उपयोग रैखिक लागत (सूचियों पैदा लेते हैं, अंत में हे है (एन^2))

someFunction check f xs = 
    [ a ++ [f x] ++ b | (a, (x:b)) <- init $ zip (inits xs) (tails xs) 
         , check x] 

अंत में (?) @ ØrjanJohansen मुझे लगता है कि एक महान उदाहरण है init $ दूर करने के लिए (मैं दोनों संस्करणों छोड़ ध्यान दें,)

बचना init $

someFunction check f xs = 
    [ a ++ [f x] ++ b | (a, (x:b)) <- zip (inits xs) (tails xs) 
         , check x] 

पिछले (xs, []) "ज़िपित" तत्व सूची समझ से बचा जाता है, @ ØrjanJohansen बताया गया है here यह कैसे अनुवाद किया है

[e | p <- l, Q] = let ok p = [e | Q] 
         ok _ = [] 
        in concatMap ok l 

(tHX @WillNess)

+0

उंगली क्या है? – aochagavia

+1

एक ट्रैवर्सिंग लेंस को उंगली के रूप में भी देखा जा सकता है। –

+1

अंतिम 'ज़िप' सुझाव अनिवार्य रूप से मुहावरे है जिसे मैं इसे जल्दी से लिखने के लिए उपयोग करता था, लेकिन मैं सिर्फ एक नोट जोड़ूंगा कि आपको 'init $' भाग की आवश्यकता नहीं है - अंतिम जोड़ी स्वचालित रूप से फ़िल्टर हो जाती है '(ए, (एक्स: बी)) 'पैटर्न। –

5

कैसे उस के बारे में:

एक सूची के साथ प्रारंभ:

[ 
[1,2,3,4], 
[1,2,3,4], 
[1,2,3,4], 
[1,2,3,4] 
] 

स्प्लिट हर पर सूचियां:

[1,2,3,4] 

कॉपी सूची n बार, एन इसका आकार (:: [[]]) किया जा रहा है तत्व (अधिक या कम "तिरछे") (:: [([], [])]):

[ 
([],[1,2,3,4]), 
([1],[2,3,4]), 
([1,2],[3,4]), 
([1,2,3],[4]) 
] 

लाइनों बाहर फ़िल्टर जिस पर head . snd अपने विधेय संतुष्ट नहीं करता

[ 
([], [1,2,3,4]), 
([1,2], [3,4]) 
] 

शेष सिर

[ 
([], [2,2,3,4]) 
([1,2], [6,4]), 
] 

जुटना जोड़े वापस

[ 
[2,2,3,4], 
[1,2,6,4] 
] 
+0

आपका मतलब "तिरछे" से क्या है? – aochagavia

+0

लेमेमे थोड़ा सा विस्तार करते हैं। –

+2

@ ओचागाविया आप वहां जाते हैं। –

9

आप इस फ़ंक्शन को टुकड़ों से इकट्ठा कर सकते हैं जो या तो मानक हैं या होना चाहिए। स्वीकृत उत्तर में ज़िप्पर के बारे में सही संकेत है। मेरा उत्तर about differentiation and comonads प्रासंगिक संचालन का सामान्य उपचार देता है, लेकिन मुझे यहां विशिष्ट होने दें।

मैं इस प्रकार "एक तत्व छेद के साथ सूची" के प्रकार को परिभाषित:

data Bwd x = B0 | Bwd x :< x deriving Show 
type HoleyList x = (Bwd x, [x]) 

सच पूछिये तो, मुझे लगता है कि ऐसा करने के लिए पिछड़े सूचियों को पेश करने की जरूरत नहीं है, लेकिन मैं अगर मैं इतनी आसानी से भ्रमित हो मेरे सिर में चीजों को उलटना है। (ऐसा होता है कि HoleyList[] का औपचारिक व्युत्पन्न है।)

अब मैं परिभाषित कर सकता हूं कि इसके संदर्भ में सूची तत्व क्या है।

type InContext x = (HoleyList x, x) 

विचार है कि इस जोड़ी के दूसरे घटक पिछड़े सूची और आगे सूची के बीच में संबंध रखता है। मैं समारोह जो वापस एक साथ सूची प्लग परिभाषित कर सकते हैं (सामान्य उपचार में upF कहा जाता है।)

plug :: InContext x -> [x] 
plug ((B0, xs), y)  = y : xs 
plug ((xz :< x, xs), y) = plug ((xz, y : xs), x) 

मैं भी समारोह है कि एक सूची के अलावा लेने के लिए सभी तरीके देता है (downF, सामान्य रूप से) को परिभाषित कर सकते हैं।

selections :: [x] -> [InContext x] 
selections = go B0 where 
    go xz [] = [] 
    go xz (x : xs) = ((xz, xs), x) : go (xz :< x) xs 

ध्यान दें कि

map snd (selections xs) = xs 
map plug (selections xs) = map (const xs) xs 

और अब हम Bartek का नुस्खा का पालन करने के लिए तैयार हैं।

selectModify :: (a -> Bool) -> (a -> a) -> [a] -> [[a]] 
selectModify p f = map (plug . (id *** f)) . filter (p . snd) . selections 

यह है: परीक्षण द्वारा चयन को फ़िल्टर करें, फोकस में तत्व को फ़ंक्शन लागू करें, फिर एक साथ प्लग करें। यदि आपके पास जिपर उपकरण के बारे में झूठ बोलना है, तो यह एक लाइनर है, और इसे किसी भी अलग-अलग मज़ेदार के लिए काम करना चाहिए, सिर्फ सूचियों के लिए नहीं! काम हो गया!

> selectModify ((1 ==) . (`mod` 2)) (2*) [1..10] 
[[2,2,3,4,5,6,7,8,9,10] 
,[1,2,6,4,5,6,7,8,9,10] 
,[1,2,3,4,10,6,7,8,9,10] 
,[1,2,3,4,5,6,14,8,9,10] 
,[1,2,3,4,5,6,7,8,18,10]] 
4

(जिसमें शामिल @ josejuan के अंतिम zip आधारित एक है, जो अनिवार्य है मुहावरा मैं जल्दी में अपने आप उपयोग करना चाहते हैं) सब अच्छा है और ज्यादातर कुछ हद तक कल्पना समाधान यहां पोस्ट के माध्यम से देख रहे हैं, मैं महसूस कर मदद नहीं कर सकता सूची में वास्तव में प्रत्यक्ष गुम है, लेकिन अभी भी स्पष्ट, आलसी रिकर्सन का उपयोग करके बेवकूफ समाधान - someFunction मानक कोड था, तो आप मानक पुस्तकालयों में शायद कोड देखेंगे। तो यहां इसका एक संस्करण है (go कर्मचारी रैपिंग सहित आप भी देखेंगे):

someFunction :: (a -> Bool) -> (a -> a) -> [a] -> [[a]] 
someFunction p f xs = go xs where 
    go [] = [] 
    go (x:xs) 
     | p x   = (f x : xs) : rest 
     | otherwise = rest 
     where 
     rest = map (x :) (go xs) 
संबंधित मुद्दे