将函数列表的组合应用于列表的每个数字



给定一个函数列表和一个数字列表,我希望将第一个函数应用于数字列表,然后将结果用于第二个函数,依此类推。

wantedFunc [(*2), (+2), (/2)] [1,2,3,4]
              |     |     |
              |     |     |
              V     |     |
        [2,4,6,8]---|     |
                    |     |
                    V     |
             [4,6,8,10]---|
                          V 
                      [2,3,4,5] -- End result

是否有内置功能?

类似

import Control.Arrow ((>>>))
wantedFunc :: Foldable t => t (a -> a) -> [a] -> [a]
wantedFunc fs = map f
  where
    f = compose fs
    compose = foldr (>>>) id

诀窍:

λ> wantedFunc [(*2), (+2), (/2)] [1, 2, 3, 4]
[2.0,3.0,4.0,5.0]

右折解决方案是:

fun :: (Functor f, Foldable t) => t (a -> a) -> f a -> f a
fun = foldr (f -> (. fmap f)) id

然后

> fun [(*2), (+2)] [1,2,3,4]
[4,6,8,10]
> fun [(*2), (+2), (`div` 2)] [1,2,3,4]
[2,3,4,5]

直接应用您的定义,我们得到

wantedFunc :: [(a -> a)] -> [a] -> [a]
wantedFunc fs xs = foldl (ys f -> map f ys) xs fs

但我们可以转变

foldl (ys f -> map f ys) xs fs
foldl (ys f -> flip map ys f) xs fs    -- flip map
foldl (flip map) xs fs                  -- remove lambda
flip (foldl (flip map)) fs xs           -- flip foldl
flip (foldl (flip map))                 -- remove lambda
flip $ foldl $ flip map                 -- or using ($)

最后

wantedFunc :: [(a -> a)] -> [a] -> [a]
wantedFunc = flip $ foldl $ flip map
另一方面,我们可以

更改函数签名翻转参数和函数列表顺序,我们可以将该函数编写为

wantedFunc' :: [a] -> [(a -> a)] -> [a]
wantedFunc' = foldr map

例如

main = do
    print $ wantedFunc  [(*2), (+2), (/2)] [1,2,3,4]
    print $ wantedFunc' [1,2,3,4] [(/2), (+2), (*2)]

带输出

[2.0,3.0,4.0,5.0]
[2.0,3.0,4.0,5.0]

这是一种fmap fmap的方法,使用 Monoid 来编写函数。

newtype Endo a = Endo { unwrap :: a -> a }
instance Monoid (Endo a) where
  mempty = Endo id
  mappend (Endo f) (Endo g) = Endo (g . f)
wantedFunc = unwrap . mconcat . fmap (Endo . fmap)
λ wantedFunc [(*2), (+2), (/2)] [1,2,3,4]
[2.0,3.0,4.0,5.0]

行解决方案可以是

> map (foldr (.) id $ reverse [(*2),(+2),(/2)]) [1..4]
[2.0,3.0,4.0,5.0]

只需组合所有函数并应用映射即可。

wantedFunc :: [a->a] -> [a] -> [a]
wantedFunc fs = map (foldl1 (.) fs)

最新更新