簡體   English   中英

Haskell 是否有 function 用於創建將 function 應用於列表的每個變體

[英]Haskell Is there a function for creating every variation of applying a function to a list

我想創建一個將 function 應用於列表的每個元素的變體列表。 這是我的意思的一個簡單示例。

applyVar f [a, b, c]
>> [[(f a), b, c], [a, (f b), c], [a, b, (f c)]]

本質上,它將 function 單獨應用於列表的每個元素,並將每個可能的應用程序存儲在一個數組中。

我不太確定如何在不使用索引的情況下解決這樣的問題,因為我聽說它們效率不高。 這是假設 function f 返回與輸入列表相同的類型。

是否有預先存在的 function 來獲得這種行為? 如果不是,那 function 會是什么?

要查看是否存在預先存在的 function,首先要弄清楚它的類型。 在這種情況下,它是(a -> a) -> [a] -> [[a]] 在 Hoogle 上搜索該類型只會返回少數匹配項,並且通過檢查,它們都沒有滿足您的要求。

要自己編寫,請注意它對列表進行操作,並且弄清楚如何在列表上編寫 function 的最佳方法是歸納定義它。 這意味着您需要構建兩種情況:一種用於空列表,另一種用於假設您已經知道其尾部答案的非空列表:

applyVar f [] = _
applyVar f (x:xs) = _ -- use `applyVar f xs` somehow

現在我們只需要填寫兩個空白。 對於 nil 的情況,這很容易。 對於 cons 情況,請注意第一個子列表以fa開頭,而 rest 將全部以a開頭。 然后,請注意 rest 的尾部看起來非常像尾部的答案。 從那里,模式應該變得清晰。

applyVar f [] = []
applyVar f (x:xs) = (f x:xs):map (x:) (applyVar f xs)

這是一個快速演示/測試:

Prelude> applyVar (+10) [1,2,3]
[[11,2,3],[1,12,3],[1,2,13]]

請注意,通常情況下, lens包含一些工具,這些工具將其作為一些更抽象工具的特例。

$ cabal repl -b lens,adjunctions
Resolving dependencies...
GHCi, version 8.10.3: https://www.haskell.org/ghc/  :? for help
> import Control.Lens
> import Control.Comonad.Representable.Store

> let updateEach f = map (peeks f) . holesOf traverse
> :t updateEach
updateEach :: Traversable t => (s -> s) -> t s -> [t s]

> updateEach negate [1..3]
[[-1,2,3],[1,-2,3],[1,2,-3]]

> import qualified Data.Map as M
> updateEach (*3) (M.fromList [('a', 1), ('b', 2), ('c', 4)])
[fromList [('a',3),('b',2),('c',4)],fromList [('a',1),('b',6),('c',4)],fromList [('a',1),('b',2),('c',12)]]

老實說,這有點矯枉過正,除非你開始需要一些lens變得更加構圖的方式,比如:

> let updateEachOf l f = map (peeks f) . holesOf l
> updateEachOf (traverse . filtered even) negate [1..5]
[[1,-2,3,4,5],[1,2,3,-4,5]]

> updateEachOf (traverse . ix 2) negate [[1,2],[3,4,5],[6,7,8,9],[10]]
[[[1,2],[3,4,-5],[6,7,8,9],[10]],[[1,2],[3,4,5],[6,7,-8,9],[10]]]

但是,無論您最終是否需要它,知道這些工具的存在都很棒。

是的。 兩個函數, initstails

foo :: (a -> a) -> [a] -> [[a]]
foo f xs = [ a ++ [f x] ++ b  | a     <- inits xs 
                              | (x:b) <- tails xs]

(帶有ParallelListComp擴展;相當於在常規列表理解中對兩個函數的兩個應用程序使用zip到相同的輸入參數xs )。

嘗試一下:

> foo (100+) [1..5]
[[101,2,3,4,5],[1,102,3,4,5],[1,2,103,4,5],[1,2,3,104,5],[1,2,3,4,105]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM