(Background: Trying to learn Haskell, very new to functional programming. Typically used to Python.)
Suppose I have a list of 2-tuples, a histogram:
let h = [(1,2),(3,5),(4,6),(5,3),(6,7),(7,4),(8,6),(9,1)]
In imperative terms, I want to change the second term of each pair to be the sum of all the previous second pairs. In Python, the following (admittedly complex) list comprehension could do it:
[(p[0], sum( [p[1] for p in histogram[:i+1]] ))
for i, p in enumerate(histogram)]
assuming histogram refers to a list of 2-tuples like h above.
Here's what I have so far in Haskell:
zip [fst p | p <- h] (scanl1 (+) [snd k | k <- h])
This works, but I wonder:
Is this reading through the list once, or twice?
Can it be expressed better? (I expect so.)
In case it isn't clear, this is the expected output for the above:
[(1,2),(3,7),(4,13),(5,16),(6,23),(7,27),(8,33),(9,34)]
You could use this function
accumulate = scanl1 step
where step (_,acc) (p1,p2) = (p1,acc+p2)
Here is the result on your sample data:
*Main> accumulate h
[(1,2),(3,7),(4,13),(5,16),(6,23),(7,27),(8,33),(9,34)]
If you're new to Haskell this might be a little too early, but lens offers a nice succinct way:
> scanl1Of (traverse . _2) (+) h
[(1,2),(3,7),(4,13),(5,16),(6,23),(7,27),(8,33),(9,34)]
You can easily accumulate only the first one by switching to _1:
> scanl1Of (traverse . _1) (+) h
[(1,2),(4,5),(8,6),(13,3),(19,7),(26,4),(34,6),(43,1)]
Or accumulate all values as a sort of nested list:
> scanl1Of (traverse . both) (+) h
[(1,3),(6,11),(15,21),(26,29),(35,42),(49,53),(61,67),(76,77)]
Well,... (,) is a Data.Bifunctor and Data.Biapplicative
scanl1 (biliftA2 (flip const) (+))
is what you want.
A Functor is such a type f that for any a can apply any function a->b to f a to get f b. For example, (a,) is a Functor: there is a way to apply any function b->c to translate (a,b) to (a,c).
fmap f (x,y) = (x,f y)
A Bifunctor is such a type f that for any a and b can apply two functions a->c and b->d to f a b to get f c d. For example, (,) is a Bifunctor: there is a way to apply any pair of functions a->c and b->d to translate (a,b) into (c,d).
bimap f g (x,y) = (f x, g y)
A Biapplicative is such a type f that for any a and b can apply f (a->c) (b->d) to f a b to get f c d. For example, (,) is a Biapplicative: there is a way to apply any functions in the pair to translate (a,b) into (c,d)
biap (f,g) (x,y) = (f x, g y)
Data.Biapplicative defines biliftA2 to "lift" a pair of functions a->c->e and b->d->f - constructs a function of two arguments of type (a,b) and (c,d)
biliftA2 f g = \(x,y) (z,t) -> (f x z, g y t)
So biliftA2 constructs a function that can be used in scanl1 to do the necessary folding. flip const will ignore the first projection of the previous pair, and (+) will add up the second projection of the previous and next pair.
Related
Despite the jargon filled title I don't think this question is very complex.
Introducing the characters
There are two important Functor combinators at play here. Flip equivalent to the haskell functiong flip but operating on types
newtype Flip p a b
= Flip
{ unFlip :: p b a
}
and Join equivalent to the W combinator on types, it takes a bifunctor and produces a functor along both its arguments
newtype Join p a
= W
{ unW :: p a a
}
Traversable
Now for Foldable it is possible to make the following instance:
instance
( forall a . Foldable (p a)
, forall a . Foldable (Flip p a)
)
=> Foldable (Join p) where
foldr g x (W xs) = foldr g (foldr g x xs) (Flip xs)
That is to say if p is foldable across both of its arguments then Join p is foldable. This is done by folding across the left and then the right.
Now I would like to make an analogous instance for Traversable, however I run into a problem. I can write sequence easily enough
sequence (W xs) = (map W . join . map (sequenceA . unFlip) . sequenceA . Flip) xs
However it seems that I need to be able to use join so I am having trouble writing sequenceA. In fact it very much seems impossible to write a sequenceA.
However I struggle to come up with a counter example. That is a p which is traversable on two arguments but not traversable when joined.
So far I've tried all the basics but none are counter examples. Join (,) is traversable
sequenceA (W (x, y)) = liftA2 (W . (,)) x y
Higher order tuples such as Join ((,,) a) are fine.
sequenceA (W (x, y, z)) = liftA2 (W . (,,) x) y z
Join Either is also traversable
sequenceA (W (Left x)) = map (W . Left) x
sequenceA (W (Right x)) = map (W . Right) x
I've come up with more examples by composing types around, which I will leave out for simplicity but needless to say they all ended up being traversable.
Is there a counter example? Can this instance be written?
Shouldn't
g a = (a,a)
in the definition of anamorphism for iterate in here? I find that, f is not applied for the zip case. Or am I reading it wrong?
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.41.125&rep=rep1&type=pdf
No, g a = (a, f a) is the correct definition. I'm not sure I understand your objection about zip; the two functions iterate and zip are not really related. They are both implemented as anamorphisms in this paper, but the similarities basically end there -- and they don't share any code other than the definition of an anamorphism.
You can verify that these definitions are correct yourself by transcribing his math to Haskell:
import Prelude hiding (iterate)
anamorphism g p b | p b = []
| otherwise = a : anamorphism g p b'
where (a, b') = g b
iterate f = anamorphism g (const False)
where g a = (a, f a)
Then, in ghci:
> take 10 (iterate succ 0)
[0,1,2,3,4,5,6,7,8,9]
This jives with the built-in:
> take 10 (Prelude.iterate succ 0)
[0,1,2,3,4,5,6,7,8,9]
I am using the Control.Foldl library to traverse an arbitrarily long list and counting all occurrences of arbitrarily many unique entities. Ie, the list may be of form
[Just "a", Just "b", Just "aab", Nothing, Just "aab"]
and I my result should something like:
[(Just "a",1),(Just "b",1) (Just "aab", 2), (Nothing, 1)]
Now the issue is I do not have the name of these entities a priori, and I would like to dynamically update the results as I fold.
My problem is that I do not know how to describe this computation in terms of the Fold data type from Control.foldl. Specifically, at each step of the fold I need to traverse the result list and ask if I have seen the current item, but I see no way of describing this using foldl.
Please note for future use purposes it's really important that I use the Control.Foldl library here, not fold over some other foldable data type like a map. In some sense my question is more along the lines of how to use the Foldl library, since the documentation is not too clear to me.
Edit: The example I showed is just a toy example, in reality I need to traverse a arb large list many times computing statistics, hence I'm using the foldl library, which allow me to combine the computations using applicatives ie toResults <$> stat1 <*> stat2 <*> ... <*> statm $ largeList and foldl allow me to traverse the list just once, computing all m statistics. Please find a solution using the foldl library.
You can encode a normal foldl' pretty straightforwardly as a Fold:
foldlToFold :: (b -> a -> b) -> b -> Fold a b
foldlToFold f z = Fold f z id
I'm actually a bit puzzled that this combinator isn't in the library...
Anyways, if you have
foldl' f z
you can replace it with
fold (Fold f z id)
so here, you would normally be using
foldl' (\mp x -> M.insertWith (+) x 1 mp) M.empty
with Fold, you'd be making
countingFold :: Ord a => Fold a (Map a Int)
countingFold = Fold (\mp x -> M.insertWith (+) 1 mp) M.empty id
and you can use it as
countUp :: Ord a => [a] -> Map a Int
countUp = fold countingFold
-- or
countUp = fold (Fold (\mp x -> M.insertWith (+) 1 mp) M.empty id)
If you want to go back to a list at the end, you can do
M.toList . countUp
In general, if you can formulate your fold as a foldl', you can do the transformation above to be able to encode it as a Fold. Fold is a bit more expressive because for foldl', the b type is both the accumulator and the result type; for a Fold, you can have a separate accumulator and result type.
Roughly speaking, you can translate any Fold into a foldl-and-map:
Fold f z g = map g . foldl' f z
And you can go backwards too:
foldlMapToFold :: (b -> a -> b) -> b -> (b -> c) -> Fold a c
foldlMapToFold = Fold
So if you had
map g . foldl' f z
you can write
fold (Fold f z g)
If you want to use a Fold, think, "how can i describe my operation as a foldl' and a map?", and then go from there.
The advantage of using the Fold type over just normal maps and folds is (apart from performance tweaks) the ability to combine and manipulate multiple Folds as objects using their Applicative instance, and other nice instances too, like Functor, Profunctor, fun stuff like that. Combining folds encoded as maps-and-foldl's is a bit tedious, but the Fold wrapper lets you do it in a cleaner first-class way using the abstractions everyone knows and loves.
For example, if i had
fold1 = map g . foldl' f z
and
fold2 = map g' . foldl' f' z'
and I wanted to do
fold3 = map (\(x,y) -> foo (g x) (g' y))
. foldl' (\(x,x') (y,y) -> (f x y, f' x' y')) (z', z')
(that is, do both folds on the list in one pas, and recombine the results at the end with foo). It's a big hassle, right?
But i can also just do
fold1 = Fold f z g
fold2 = Fold f' z' g'
fold3 = foo <$> fold1 <*> fold2
(Note that, even better, using using Fold actually keeps foldl' strict, because in the example above, the lazy tuples add a layer of indirection and make the fold' lazy again incidentally)
I use this a fair bit:
a' = [ (f x, f y) | (x, y) <- a ]
Is there a better way to do that?
You can use the (***) operator from Control.Arrow
> map (f *** f) a
or define your own helper function
> let both f (x, y) = (f x, f y)
> map (both f) a
Alternative solution:
import Data.Bifunctor
bimap f f pair
Bifunctor.bimap is basically the same as Arrow.(***), but works for other bifunctors (like Either a b), too.
Digression:
The reason why there is nothing predefined for your case is that you can't write instances of Functor, Applicative etc for (,) having the same element type twice. With an own "vector-like" type you wouldn't have this problem:
data Pair a = Pair a a deriving Show
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
Now you can write things like map (fmap (+1)) [Pair 12 14, Pair 17 18]. Or if you want to use different operations on your Pair, you can go one step further:
instance Applicative Pair where
pure x = Pair x x
(Pair f g) <*> (Pair x y) = Pair (f x) (g y)
If you work a lot with same-element-type pairs, it could be useful to switch from (,) to such a type.
If you use lens, you can use over both f, or both %~ f. This has the advantage of being more composable -- for example, if you have a pair of lists, you can use something like both.mapped +~ toUpper (:: ([Char],[Char]) -> ([Char],[Char])).
I was bored one day and wanted to exercise my brain, so I decided to do the 99 Haskell Problems but restricted myself to doing them in point-free style. A problem that seems to crop up a lot when I'm doing things in point-free style is this: How do you apply multiple functions to the same value while keeping each result as an independent entity? Using pointed notation:
foobar x = [id x, reverse x]
And what I've come up with so far in point-free notation:
foobar' = `map` [id, reverse] ($ x)
I can't seem to get that x off the end of there.
Others have already posted how you can do this using the Reader monad, but that's not the only way. It turns out that your second function is pretty close. I think you meant to post
foobar' x = (`map` [id, reverse]) ($ x)
Since the x is already near a rightmost position, you're almost there. First, transform the section ($ x) into a function, because it's a bit easier to work with:
-- by the definition of a right operator section
foobar'2 x = (`map` [id, reverse]) (\y -> ($) y x)
Next remove the x from the lambda body by bringing a new variable into scope, and applying the function to x
-- lambda abstraction I think...
foobar'2 x = (`map` [id, reverse]) $ (\z y -> ($) y z) x
Rewrite this application as a function composition, and then you can eta reduce:
-- by definition of '.'
foobar'3 x = (`map` [id, reverse]) . (\z y -> ($) y z) $ x
-- eta reduction
foobar'4 = (`map` [id, reverse]) . (\z y -> ($) y z)
Finally, notice that we can replace the lambda with a function
-- by definition of `flip`
foobar'5 = (`map` [id,reverse]) . flip ($)
and you have a point-free form.
You will be interested in the Applicative instance of the reader monad:
instance Applicative (e ->)
Using it you can easily distribute an argument:
liftA2 (+) sin cos 3
Here sin and cos are functions, which both receive the value 3. The individual results are then combined using (+). You can further combine this with the Category instance of (->), but of cource specialized versions of (.) and id are already defined in the Prelude.
Background: The Applicative instance for (e ->) really represents the SKI calculus, where (<*>) is the S combinator and pure is the K combinator. S is precisely used to distribute an argument to two functions:
S f g x = f x (g x)
It takes a function application (f g) and makes both dependent on the value x ((f x) (g x)).
Use sequence:
> let foobar' = sequence [id, reverse]
> foobar' "abcde"
["abcde","edcba"]
There are a few basic idiomatic combinators which pop up repeatedly, and are reimplemented with various higher concepts and libraries, but which are essentially very simple. Names may vary, and some are implementable in terms of others:
fork (f,g) x = (f x, g x) -- == (f &&& g)
prod (f,g) x = (f $ fst x, g $ snd x) -- == (f *** g)
pmap f (x,y) = (f x, f y) -- == (f *** f)
dup x = (x,x)
etc. Of course uncurry f (x,y) == f x y gets used a lot with these, too.
&&& and *** are defined in Control.Arrow, as well as first and second. Then prod (f,id) == first f, prod(id,g) == second g etc. etc.
So your foobar becomes
foobar = (\(a,b)->[a,b]) . fork (id,reverse)
= (\(a,b)->[a,b]) . (id &&& reverse)
= (\(a,b)->[a,b]) . (id *** reverse) . dup
= join $ curry ( (\(a,b)->[a,b]) . second reverse)
For the last one you need to also import Control.Monad and Control.Monad.Instances. See also this question.
late edit: also, using Control.Applicative as hinted in answer by ertes,
= (:) <*> ((:[]) . reverse)