2009-03-18 12 views
9

Si tratta dello zucchero sintattico in Haskell. Un semplice programma Haskell:Come mescolare il binding (<-) e l'assegnazione (let) in una riga? (in Haskell)

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

io uso vincolante nella prima riga (args <- getArgs) ed un'assegnazione puro nella seconda (let first = ...). È possibile unirli in un unico rivestimento leggibile?

ho capito che posso riscrivere vincolante “de-zuccherato”:

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

Ma c'è un modo migliore, senza ingombrare la linea con (>> =) e ritorno?

risposta

16

liftM e head sono tutti molto bene, ma non dobbiamo dimenticare pattern matching:

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

o se vi piace il layout

main = do 
    arg : _ <- getArgs 
    print arg 

Se possibile, la maggior parte degli Haskeller preferiscono la corrispondenza del modello su head e tail.

+0

Questo è veramente bello e leggibile. Grazie! – sastanin

+0

~ [arg] <- getArgs – Dario

9

Che ne dici di questo?

import Control.Monad 

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

D'oh! 19 secondi più veloce di me. – ephemient

+0

e molto più veloce di me :) – Jonas

+0

Sì, questo è molto più costoso. Grazie! – sastanin

6

E 'anche possibile utilizzare la funzione ap (con il tipo Monad m => m (a -> b) -> m a -> m b) come questo:

import System 
import Control.Monad 

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

Questo ha il semplice vantaggio che se la funzione richiede diversi argomenti è possibile utilizzare ap tra ciascuno dei loro e non c'è bisogno di usare liftM2, liftM3 ecc per una funzione f::a -> b -> c -> d si scrive

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

Grazie. Non sapevo di "ap". – sastanin

+0

per quelli con un gusto applicativo, 'ap' = <*> e' liftM' = <$> – Eli

1

Come sono ingombri bind e return?

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

o

main = liftM head getArgs >>= print

+2

Di solito penso a return come "wrap into monad", e (>> =) come "unwrap and substitute". Quindi leggere il codice è qualcosa come "scartare e sostituire, e avvolgere di nuovo, scartare e sostituire". Quindi, liftM è più leggibile per me, perché è semplicemente "rendere la funzione monadica". Quindi, mi piace l'opzione 2. – sastanin

10

Ancora un'altra possibilità:

main = putStr . head =<< getArgs 
+0

Beh, è ​​bello. Non ho pensato alla versione invertita. Grazie. – sastanin

Problemi correlati