On Mon, Sep 15, 2014 at 10:38 PM, Ben Mabey <
b...@benmabey.com> wrote:
> One thing I did want while writing my solution was Clojure's threading
> operator (macro). The threading operator is like the thrush combinator[1]
> but uses code rewrites so it is slightly different than normal function
> composition. The main idea though is that you can write code like:
>
> (defn validate [x]
> (-> x to-digits double-every-other sum-digits (mod 10) zero?))
>
> Contrast that to regular function composition that reads "backwards" and the
> mod operator is on the outside of everything else:
>
> validate x = (mod ((sumDigits . doubleEveryOther . toDigits) x) 10) == 0
>
> I found this SO talking about how to do something similar in Haskell
> w/Control.Arrow or rolling your own function:
>
>
https://stackoverflow.com/questions/9545816/is-there-a-name-for-a-function-that-takes-a-piece-of-data-and-a-list-of-function
I have used the foldr technique in real code that needs to apply a
dynamic number of validation functions to a user-supplied value, but
if the functions to apply are known statically then it'd best to
directly compose them. This leaves more optimization opportunities
open to the compiler.
> How common is Control.Arrow or similar constructs used in Haskell code? The
> threading operator is idiomatic in clojure so I'm trying to get feel for how
> common that pattern is in Haskell.
Control.Arrow combinators are used frequently by people trying
extra-hard to write point-free code (i.e. building functions by
composing combinators instead of lambdas with arguments) and not much
at all by people who use a more traditional Haskell style. I'd
recommend against them at first, but it's good to know about them
eventually as you will find a few examples in the wild.
When you're dealing with a function where the arguments are in the
"wrong" order for convenient composition, there are a couple of ways
to handle it. First, there's the `flip` combinator that reverses the
order of the arguments: (flip mod 10). Second, you can take
advantage of two syntactic features--using backticks to turn a named
function into an operator and operator sections--to create a
partially-applied function: (`mod` 10). Using this technique, you'd
get something like the following:
validate = (== 0) . (`mod` 10) . sumDigits . doubleEveryOther . toDigits
Haskell programmers have traditionally found function composition
order to be more natural to use than the "threading" order created by
Clojure's -> macro, so there aren't any standard ways of creating
them. Many Haskell-hosted DSLs have such a feature, but I'd recommend
trying to get used to normal function composition order, as it's by
far the most commonly used idiom in Haskell.