sastanin
sastanin

Reputation: 41541

How to mix binding (<-) and assignment (let) in one line? (in Haskell)

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?

Upvotes: 10

Views: 2038

Answers (5)

Jonas
Jonas

Reputation: 19642

Yet another possibility:

main = putStr . head =<< getArgs

Upvotes: 10

ja.
ja.

Reputation: 4249

How are bind and return clutter?

main = getArgs >>= (return.head) >>= print

or

main = liftM head getArgs >>= print

Upvotes: 1

Norman Ramsey
Norman Ramsey

Reputation: 202655

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.

Upvotes: 16

Jonas
Jonas

Reputation: 19642

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

Upvotes: 6

cthulahoops
cthulahoops

Reputation: 3835

How about this?

import Control.Monad

main = do
   first <- liftM head getArgs
   print first

Upvotes: 9

Related Questions