2016-12-08 70 views
2

所以我經常發現自己設計'流水線'就像數據流一樣,通常情況下,流水線本身是動態的。通過動態功能列表管道數據

有沒有簡單的方法來做這樣的事情?

pipe :: [a -> a] -> a -> a 

還是有不同的模式,我應該與這樣的事情達成?它類似於國家monad,但我不想編輯功能(a ->(), a)或任何:/

我意識到這是一個monoid,所以我寫了這個,這似乎是一個優雅的解決方案,這是否存在於某個圖書館?看起來大多數Arrow和Function Monoid都做了不同的事情。

newtype Comp a = Comp { 
     runComp :: a -> a 
} 

instance Monoid (Comp a) where 
    (Comp a) `mappend` (Comp b) = Comp (b . a) 
    mempty = Comp id 

pipe :: [a -> a] -> a -> a 
pipe = runComp . foldMap Comp 

任何人都有他們用於這種事情的模式?謝謝!

+1

從* A A射*爲* A *被稱爲[endomorphism](https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Monoid.html#t:Endo)。你的'Comp' monoid是'Dual。 Endo'。 – Zeta

+1

多態流水線?我懷疑這裏可能存在X/Y問題。你打算如何使用它? – leftaroundabout

+0

是的,正如@leftaroundabout似乎暗示的那樣,如果你需要能夠將列表分開,並且組成其中的功能,你只需要這種奇特的機器。否則,你應該只是處理構圖並擺脫列表。 – dfeuer

回答

5

您正在尋找的

foldr (.) id  -- right-to-left 

foldl (flip (.)) id -- left-to-right 

一個,這取決於訂購您想要的功能組成:

ghci> foldr (.) id [(+1),(*10)] 0 
1 
ghci> foldl (flip (.)) id [(+1),(*10)] 0 
10 
+2

或者,如果你想留在'Monoid'的模糊領域:'appEndo。 foldMap Endo'和'(appEndo。getDual)。 foldMap(Dual。Endo)'。順便說一句,我希望你不要介意這個例子。 – Zeta

+2

我通常爲此使用'foldr(。)id' - 是否有任何理由在此使用'foldl'? – chi

+0

@Zeta這不是再次使用'stimesMonoid'的地方嗎? – Alec