This is a short post explaining why you should prefer do notation when assembling a record, instead of using Applicative operators (i.e. (<$>)/(<*>)). This advice applies both for type constructors that implement Monad (e.g. IO) and also for type constructors that implement Applicative but not Monad (e.g. the Parser type constructor from the optparse-applicative package). The only difference is that in the latter case you would need to enable the ApplicativeDo language extension. The guidance is pretty simple. Instead of doing this: data Person = Person { firstName :: String , lastName :: String } getPerson :: IO Person getPerson = Person <$> getLine <*> getLine … you should do this: {-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -Werror=missing-fields #-} data Person = Person { firstName :: String , lastName :: String } getPerson :: IO Person getPerson = do firstName <- getLine lastName <- getLine return Person{..} Why is the latter version better? There are a few reasons. Ergonomics It’s more ergonomic to assemble a record using do notation because you’re less pressured to try to cram all the logic into a single expression. For example, suppose we wanted to explicitly prompt the user to enter their first and last name. The typical way people would do extend the former example using Applicative operators would be something like this: getPerson :: IO Person getPerson = Person <$> (putStrLn "Enter your first name:" *> getLine) <*> (putStrLn "Enter your last name:" *> getLine) The expression gets so large that you end up having to split it over multiple lines, but if we’re already splitting it over multiple lines then why not use do notation? getPerson :: IO Person getPerson = do putStrLn "Enter your first name:" firstName <- getLine putStrLn "Enter your last name:" lastName <- getLine return Person{..} Wow, much clearer! Also, the version using do notation doesn’t require that the reader is familiar with all of the Applicative operators, so it’s more approachable t...
First seen: 2026-04-02 23:05
Last seen: 2026-04-03 06:08