

Applicative Programming, Disjoint Unions, Semigroups and Non-breaking Errors - pufuwozu
http://applicative-errors-scala.googlecode.com/svn/artifacts/0.6/chunk-xhtml/index.html

======
samstokes
The title is facetiously obfuscated (though accurate): this is about
performing a sequence of computations which might throw errors (such as
validating input), collecting those errors along the way.

The punchline:

    
    
        val f = (Person(_, _, _)).curried
        val age = validAge(args(0))
        val name = validName(args(1))
        val postcode = validPostcode(args(2))
    
        postcode <<*>> (name <<*>> (age map f)) match {
          case Success(p) => println("We have a person: " + p)
          case Failure(e) => e foreach println
        }
    

I'm puzzled by the author's choice of argument order, which means the call to
the Person constructor at the end has to be reversed (arguments in reverse
order with `f` at the end). In Haskell, using the built-in Applicative
typeclass and flipping his definitions of <<star>> and vmap:

    
    
        instance Functor (Validation e) where
          fmap = flip vmap
        
        instance Semigroup e => Applicative (Validation e) where
          pure = Success
          (<*>) = flip (<<*>>)
    

you can write the constructor call in the natural order:

    
    
        Person <$> age <*> name <*> postcode
    

which is obviously analogous to what the call would look like without error
handling:

    
    
        Person age name postcode
    
    

IMHO this shows the power of the technique described more clearly: that with a
bit of plumbing up front, you can add arbitrarily sophisticated error handling
behaviour _without_ much disruption to existing code.

One of my Haskell 'aha' moments was that you could do this with Parsec (a
parsing library) to build data structures in a way that mirrors the grammar
being parsed:

    
    
        data Section = HostSection {hostNames :: [String], hostOptions :: [HostOption]}
    
        hostSectionP :: CharParser st Section   -- hostSectionP parses Chars and produces a Section
        hostSectionP = HostSection <$> hostHeaderP <*> many1 hostOptionP
          -- many1 is like '+' in regex

------
pufuwozu
PDF version:

[http://applicative-errors-
scala.googlecode.com/svn/artifacts...](http://applicative-errors-
scala.googlecode.com/svn/artifacts/0.6/pdf/index.pdf)

------
T_S_
Nice quote: "Non-breaking error handling is just an applicative functor on a
partially applied disjoint union type constructor with semigroup error
elements so what's the big deal?!"

------
loewenskind
From the Haskell code it looks to me like the <<*>> operator is doing a monoid
append, no?

