2017-06-19 77 views
9

我正在尋找過濾遍歷,然後選擇要使用的最後一個元素與over遍歷「過濾」的最後一個元素

例如這樣的事情(但其實將編譯):

[1,2,3,4] & traverse . filtered even . _last +~ 10 
> [1,2,3,14] 

任何想法?

P.S.我知道filtered只有在不影響遍歷中元素的數量時纔有效。

我正在執行的實際用例是僅選擇匹配某個謂詞的遞歸uniplate遍歷的最低級別;如果你有其他的想法如何做到這一點,我很樂意聽到他們!

+0

我在通過遍歷反向狀態monad變換器來做這件事上有一個破解,但是這給了你一個簽名'MonadFix m => Traversal'sa - > LensLike'msa'不是非常有用 - 你只能將值放入它中,而不能將它們取出,因爲Const s不是Monad。另一種方法是通過摺疊獲得集合的長度,然後將狀態計數到最後一個索引 - 這會給你一個「Monad」約束,而不是「MonadFix」,而犧牲一些效率。在@ Gurkenglas的回答中,通過一個具體的名單,可能是你最好的選擇 –

回答

1

這不是一個真正的答案,只是@Gurkenglas的後續行動,這對於評論來說太大了。需要注意的是@ Gurkenglas的回答是:

let t = partsOf (traverse . filtered even) . _last 

可以看起來像穿越,但它不是,即使你保持元件數量,因爲它違反了第二穿越定律(原因很明顯):

let f = Identity . succ 
[1,2,3,4] & fmap (t f) . t f -- yields [1,3,3,5] effectively 
[1,2,3,4] & getCompose . t (Compose . fmap f . f) 
           -- yields [1,2,3,6] effectively 

因爲這是一個穿越,你必須保持的元素計數過濾性質爲不變量。

這是否會影響您的應用程序,但我不知道,但請注意partsOf附帶了這些注意事項,並且文檔誤導性地表明partsOf的結果將成爲Lens如果您維護該元素計數。 (對於partsOf each,在文檔中給出的例子是這樣的,但不是一般的。)

2
[1,2,3,4] & partsOf (traverse . filtered even) . _last +~ 10