Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Mapping" scanl

Given a list :: [(Foo, Bar)], I'd like to perform a scanl1 on the Bars, but preserve their Foo "tags".

I.e. I'd like a function with the type :: [(a, b)] -> ([b] -> [c]) -> [(a, c)], so that I can pass a curried scanl1 as the second argument.

I can write it recursively, but it feels like there's a way to compose higher-order functions to do this.

Is this already possible with standard functions?

like image 764
amindfv Avatar asked Aug 30 '12 19:08

amindfv


2 Answers

Instead of writing an unsatisfying higher order function, you could lift your combining function to thread the Foo tags through so you can still use scanl1 , which is what you mean.

keeptags :: (Bar -> Bar -> Bar) -> (Foo,Bar) -> (Foo,Bar) -> (Foo,Bar)
keeptags g (_,b) (a',b') = (a',g b b')

Now you can use scanl1; take your original qux :: Bar -> Bar -> Bar and make

scanQux :: [(Foo,Bar)] -> [(Foo,Bar)]
scanQux = scanl1 (keeptags qux) 

keeptags is simple and scanQux is crystal clear.

For example, if

type Foo = Char
type Bar = Int

qux = (+)

then you get

*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)]

as you had hoped.

like image 118
AndrewC Avatar answered Sep 25 '22 03:09

AndrewC


You mean, unzip?

http://zvon.org/other/haskell/Outputprelude/unzip_f.html

x = zip a c
  where
    (a, b) = unzip my_list
    c = what_ever_you_want_on b
like image 23
lvella Avatar answered Sep 25 '22 03:09

lvella