top | item 9704696

(no title)

dons | 10 years ago

Habitually rewriting things in applicative and/or pointfree is a sure sign of a junior Haskell dev. One who has never had to maintain someone else's code.

There are cases where it helps (e.g. structured parsing), but all too often this is simply obfuscation. Even if motivation is good -- learning new structures -- you still have to focus on cost/benefit of each change in structure.

Keep it simple, folks.

discuss

order

chriswarbo|10 years ago

I'm generally in favour of introducing applicatives, but I don't think the code in the article is a good example:

    (bid, now) <- liftIO $ do
        b <- randomIO
        n <- getCurrentTime
        return (b, n)

    (bid, now) <- liftIO $ (,)
        <$> randomIO
        <*> getCurrentTime
The applicative code could be considered better, since it avoids one-shot variables. However, that's not the biggest smell with this code. To me, the problems are:

- Constructing-then-destructing a pair; is it really necessary?

- Use of `$`; is there a way to avoid having to alter the precedence?

- Combining two seemingly unrelated actions into one; `randomIO` should be completely uncorrelated to the current time, so why put them in the same action?

- Potential laziness issues; it looks like we're using the `(bid, now)` combination to ensure the two IO actions are executed together, but will they be? WHNF will give us `(_ , _)`; if we force `bid`, will `now` also be forced?

Not saying I have answers to these, but I would say those are more "smelly" than the do-notation with a return

tome|10 years ago

Code review 4 lines: hundreds of comments

Code review 1000 lines: "Looks fine"

reagency|10 years ago

How would you write it? Creating a pair does seem weird, unless those two values are going to be passed around through multiple method calls together for use in multiple locations.