2009-03-18 7 views
9

Hier geht es um syntaktischen Zucker in Haskell. Ein einfaches Programm Haskell:Wie Binding (<-) und Zuweisung (Let) in einer Zeile mischen? (in Haskell)

main = do 
    args <- getArgs 
    let first = head args 
    print first 

I in der ersten Zeile (args <- getArgs) und eine reine Zuordnung in dem zweiten (let first = ...) Bindung verwenden. Ist es möglich, sie zu einem lesbaren Einzeiler zusammenzufügen?

Ich verstehe, dass ich neu schreiben kann „de-gezuckert“ Bindung:

main = do 
    first <- getArgs >>= (return . head) 
    print first 

Aber gibt es eine schönere Art und Weise, ohne mit der Linie unübersichtlich (>> =) und zurück?

Antwort

16

liftM und head sind alle sehr gut, aber lassen Sie uns nicht Musterabgleich vergessen:

main = do { arg:_ <- getArgs; print arg } 

oder wenn Sie wie das Layout

main = do 
    arg : _ <- getArgs 
    print arg 

Wenn möglich, bevorzugen die meisten Haskeller die Mustererkennung über head und tail.

+0

Das ist wirklich nett und lesbar. Vielen Dank! – sastanin

+0

~ [arg] <- getArgs – Dario

9

Wie wäre es damit?

import Control.Monad 

main = do 
    first <- liftM head getArgs 
    print first 
+0

D'oh! 19 Sekunden schneller als ich. – ephemient

+0

und viel schneller als ich :) – Jonas

+0

Ja, das ist viel nicer. Vielen Dank! – sastanin

6

Es ist auch möglich, die ap Funktion (mit Typ Monad m => m (a -> b) -> m a -> m b) wie folgt zu verwenden:

import System 
import Control.Monad 

main :: IO() 
main = do line <- return head `ap` getArgs 
      putStrLn line 

Dies hat den einfachen Vorteil, dass, wenn Ihre Funktion mehrere Argumente erfordert, dass Sie von ap zwischen jedem verwenden können sie und Sie brauchen nicht liftM2 zu verwenden, liftM3 etc. Für eine Funktion f::a -> b -> c -> d Sie schreiben

return f `ap` arg1 `ap` arg2 `ap` arg3 
+0

Vielen Dank. Ich wusste nichts von "ap". – sastanin

+0

für diejenigen mit einem anwendbaren Geschmack, ap = <*> und 'liftM' = <$> – Eli

1

Wie sind Bind und Return Clutter?

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

oder

main = liftM head getArgs >>= print

+2

Ich denke normalerweise über Rückkehr als" wrap in monad "und (>> =) als" unwrap and substitute ". Das Lesen des Codes ist also etwas wie "auspacken und ersetzen, und wieder einwickeln und auspacken und ersetzen". LiftM ist also für mich besser lesbar, weil es einfach "Funktion monadisch machen" ist. Also, ich mag Option 2. – sastanin

10

Noch eine weitere Möglichkeit:

main = putStr . head =<< getArgs 
+0

Nun, es ist schön. Ich habe nicht an eine umgekehrte Version gedacht. Vielen Dank. – sastanin