4 ms·
Applicative Programming, Disjoint Unions, Semigroups and Non-breaking Errors
- pufuwozu 16y agoPDF version: http://applicative-errors-scala.googlecode.com/svn/artifacts/0.6/pdf/index.pdf http://applicative-errors-scala.googlecode.com/svn/artifacts...
- T_S_ 16y agoNice 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?!"
- samstokes 16y agoThe 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
- loewenskind 16y agoFrom the Haskell code it looks to me like the <<*>> operator is doing a monoid append, no?