How to mix binding (<-) and assignment (let) in one line? (in Haskell)
-
20-08-2019 - |
Question
This is about syntactic sugar in Haskell. A simple Haskell program:
main = do
args <- getArgs
let first = head args
print first
I use binding in the first line (args <- getArgs
) and a pure assignment in the second one (let first = ...
). Is it possible to merge them together into a readable one-liner?
I understand that I can rewrite binding “de-sugared”:
main = do
first <- getArgs >>= ( return . head )
print first
But is there a nicer way, without cluttering the line with (>>=) and return?
Solution
liftM
and head
are all very well, but let us not forget pattern matching:
main = do { arg:_ <- getArgs; print arg }
or if you like layout
main = do
arg : _ <- getArgs
print arg
When possible, most Haskellers prefer pattern matching over head
and tail
.
OTHER TIPS
Yet another possibility:
main = putStr . head =<< getArgs
How about this?
import Control.Monad
main = do
first <- liftM head getArgs
print first
It is also possible to use the ap
function (with type Monad m => m (a -> b) -> m a -> m b
) like this:
import System
import Control.Monad
main :: IO ()
main = do line <- return head `ap` getArgs
putStrLn line
This has the simple advantage that if your function requires several arguments you can use ap
between each of them and you don't need to use liftM2
, liftM3
etc. For a function f::a -> b -> c -> d
you write
return f `ap` arg1 `ap` arg2 `ap` arg3
How are bind and return clutter?
main = getArgs >>= (return.head) >>= print
or
main = liftM head getArgs >>= print