‘traverse :: Applicative f => (a -> f b) -> t a -> f (t b)’
And you can derive it for free for your own datatypes!
The amount of code I’ve manually written in other languages to get a similar effect is painfully large.
‘traverse :: Applicative f => (a -> f b) -> t a -> f (t b)’
And you can derive it for free for your own datatypes!
The amount of code I’ve manually written in other languages to get a similar effect is painfully large.
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
and deriving it for your own types is as simple as data MyType ... = ... deriving (Traversable)I understand how Applicative works, but I don’t know how to apply (pun intended) to my data types.
For one client, we needed to accumulate some extra statistics for each. For another, we needed to call their web API (so async I/O) to get some of the data used in the report. By making the generic superclass use a generic Applicative type, we could keep the report business logic clear and allow the client-specific subclasses to do these client-specific things and have them compose the right way.
Wanting custom applicative types is rarer than using a standard one, but it can be a good way to represent any kind of "secondary effect" or "secondary requirement" that your functions might have. E.g. "requires this kind of authorisation" or "must happen in a database transaction". But a lot of the time you can implement custom things using reader/writer/state, or free, rather than having to write a completely from-scratch applicative.
Besides Maybe/Either `t` could represent anything, like container types Lists/Trees/Hashmaps etc, but also more complicated structures like syntax trees for programming languages or custom DSLs. Or (my favorite use case!) recursive command types for robot control. I'm doing this mostly in Rust, but borrow all the ideas from Haskell.