News for hackers. Stuff that matters.
Re:Applicative WTF? by platz on Tuesday October 23, 2018 @05:02PM (#18287454)
> Last time I used Haskell, Applicative wasn't even a thing. I had read the McBride and Paterson paper that introduced applicative functors, but that was years ago, and I didn't remember any of the details.

In the previous post he learns how to use an Applicative.

In this post, he learns how to define Applicative for a new type he's created.

Yes, Applicative is abstract enough that it takes a few concrete examples to get a feel for it and grok what it's purpose is.

This is the work that's required to learn a new abstraction. All abstractions that are sufficiently different from previous experience require this kind of effort to make it legible to you.

Once you do, it kind of just 'snaps' and you get it.

Then, you get to leverage that knowledge in all the places it is re-used, instead of having to read the library code doing data manipulation in a bespoke way - you can just look at the type can say "yes, this is an Applicative - i know how to manipulate it and it will accord to some laws i can depend on", without having to read the source code.

Re:Applicative WTF? by nybble41 on Tuesday October 23, 2018 @05:31PM (#18287687)
Given that he already knew how to define a Monad instance for his type, the Applicative instance could simply be:

    import Control.Monad (ap)
    instance Applicative Tree where
       pure  = return
       (<*>) = ap
Also, given a Traversable instance—which is essentially just "fmap with effects"—one can get Foldable and Functor for free via foldMapDefault and fmapDefault.

The really interesting cases are the ones where you can define an instance for Applicative but not Monad.

Re:Applicative WTF? by pinjo on Wednesday October 24, 2018 @10:48AM (#18292873)
An example of this is the two possible applicative instance of list. One is based on the monad instance and does a cross product if presented with two lists. The other zips its arguments. It is the more interesting one imho:

    import Control.Applicative 
    newtype ZList a = ZList { runZList :: [a] } 
    instance Functor ZList where 
        fmap f = ZList . fmap f . runZList

    instance Applicative ZList where 
        pure a = ZList [a]
        (<*>) f x = ZList $ zipper (runZList f) (runZList x)
                where zipper (f:fs) (x:xs) = f x : zipper fs xs 
                      zipper [] _ = [] 
                      zipper _ [] = []
Difference of behaviour:

   *Main> ZipList [(*3),(*5),(*6)] <*> ZipList [1,2,3,4] 
    ZipList {getZipList = [3,10,18]}
   *Main> [(*3),(*5),(*6)] <*> [1,2,3,4]
    [3,6,9,12,5,10,15,20,6,12,18,24]
    *Main>
Re:Applicative WTF? by nybble41 on Wednesday October 24, 2018 @11:40AM (#18293350)
Yes, though that definition results in:

    pure id <*> ZipList [x, y, z] == ZipList [x]
and thus breaks one of the Applicative laws:

    pure id <*> v == v
The standard ZipList definition is `pure a = ZipList (repeat a)` (an infinite list).

The issue with defining a Monad instance for ZList is that mapping the function on the right of (>>=) over the ZList on the left gets you a ZList of `ZList b`, with no meaningful way to zip these ZLists together.

Re:Applicative WTF? by platz on Tuesday October 23, 2018 @05:37PM (#18287736)
Right

It is interesting that he knew this fact,and that it would be nice if this code could be automatically derived too, but I think that should not replace the learning process.

It is more of a nit for advanced users

Re:Applicative WTF? by nybble41 on Tuesday October 23, 2018 @06:56PM (#18288216)
Indeed, the learning process is important. I think it's particularly instructive to look at how `ap` is implemented, and what is left out in the transition from Monad to Applicative:

    mf `ap` ma = do
       f <- mf
       a <- ma
       return (f a)
With a Monad, the action on the right of the bind operator is a function of the result of the action on the left. The second operand of the `ap` function, however, does not have any access to the result of the first operand. The two operands are evaluated independently, apart from their side-effects. That reflects the fundamental difference between Applicative and Monad: an Applicative instance just sequences effects and combines results, whereas a Monad instance allows effects to depend on previous results.
Re:Applicative WTF? by taejo on Wednesday October 24, 2018 @08:06AM (#18291664)
Does this mean that many Monads have two possible Applicative instances? For the two orders of "running" mf and ma?
Re:Applicative WTF? by nybble41 on Wednesday October 24, 2018 @11:55AM (#18293509)
All Applicatives have those two variants, not just Applicatives which are also Monads. There is a Backwards newtype in Control.Applicative.Backwards which reverses the order of effects for any Applicative:

    GHCi> import Control.Applicative.Backwards
    GHCi> :i Backwards
    newtype Backwards (f :: k -> *) (a :: k)
      = Backwards {forwards :: f a}
    GHCi> forwards $ (++) <$> Backwards ("foo" <$ print 1) <*> Backwards ("bar" <$ print 2)
    2
    1
    "foobar"
As you can see, the result is the same but the effects are reversed. The definition is simple:

    instance Applicative f => Applicative (Backwards f) where
       pure = Backwards . pure
       Backwards f <*> Backwards a = Backwards $ (flip ($)) <$> a <*> f
Re:Applicative WTF? by lmm on Wednesday October 24, 2018 @09:37AM (#18292260)
I don't know about "many", but certainly some - e.g. you could form a "reversed MonadWriter" applicative that would write the messages from ma before the messages from mf. For a lot of monads the effects are commutative though, in which case the "two possible" Applicatives are actually the same, e.g. Maybe obviously behaves the same whichever order you "run" mf and ma in.
Re:Applicative WTF? by taejo on Friday October 26, 2018 @03:44AM (#18307470)
My "many" exactly meant to exclude the commutative case :)
Re:Applicative WTF? by tomjakubowski on Tuesday October 23, 2018 @06:53PM (#18288200)
Re:Applicative WTF? by pjmlp on Wednesday October 24, 2018 @04:36AM (#18290646)
Yet another reason why learning Algorithms + Data Structures + Paradigms is much more powerful than focusing too much on language specifics.