"映射"scanl

ami*_*dfv 6 haskell higher-order-functions

给定一个列表:: [(Foo, Bar)],我想在Bars 上执行scanl1 ,但保留它们的Foo"标签".

即我想要一个具有该类型的函数:: [(a, b)] -> ([b] -> [c]) -> [(a, c)],以便我可以传递curried scanl1作为第二个参数.

我可以递归地编写它,但感觉有一种方法来组成高阶函数来做到这一点.

这是否已经可以使用标准功能?

And*_*ewC 11

您可以提升组合功能,使Foo标签穿过,而不是写出令人不满意的高阶函数,这样您仍然可以使用scanl1,这就是您的意思.

keeptags :: (Bar -> Bar -> Bar) -> (Foo,Bar) -> (Foo,Bar) -> (Foo,Bar)
keeptags g (_,b) (a',b') = (a',g b b')
Run Code Online (Sandbox Code Playgroud)

现在你可以用scanl1; 拿你的原创qux :: Bar -> Bar -> Bar和制作

scanQux :: [(Foo,Bar)] -> [(Foo,Bar)]
scanQux = scanl1 (keeptags qux) 
Run Code Online (Sandbox Code Playgroud)

keeptags很简单,scanQux也很清晰.

例如,如果

type Foo = Char
type Bar = Int

qux = (+)
Run Code Online (Sandbox Code Playgroud)

然后你得到

*Main> scanl1 qux [1..9]
[1,3,6,10,15,21,28,36,45]

*Main> zip "HELLO MUM" [1..9]
[('H',1),('E',2),('L',3),('L',4),('O',5),(' ',6),('M',7),('U',8),('M',9)]

*Main> scanQux $ zip "HELLO MUM" [1..9]
[('H',1),('E',3),('L',6),('L',10),('O',15),(' ',21),('M',28),('U',36),('M',45)]
Run Code Online (Sandbox Code Playgroud)

正如你所希望的那样.