2012-04-10 8 views
5

Un ejemplo de juguete, pero aún frustrante:Haskell lanza un error de análisis en un lugar extraño

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] (\num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code) 
        let numberCodes = zip [1 .. 4] codes 
        in forM numberCodes (\(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num) 

ghci me dice que tengo un Parse error in pattern: putStrLn y no puedo entender por qué debería dejar de analizar.

+1

Ok, esto funciona si agrego llaves para los bloques do y los puntos y coma al final de cada 'declaración', pero ¿es esa la solución recomendada? (parece poco funcional: P) – agam

+0

Puede fingir que los puntos y comas ya están allí, pero son invisibles. (Hay reglas para donde van las llaves automáticas y el punto y coma.) –

Respuesta

10

Corrección:

numberMapper:: IO() 
numberMapper = do 
    codes <- forM [1 .. 4] $ \num -> do 
     putStrLn $ "Enter a code for " ++ show num 
     getLine 
    let numberCodes = zip [1 .. 4] codes 
    forM_ numberCodes $ \(num,code) -> 
     putStrLn $ "Got code " ++ show code ++ " for " ++ show num 

Fix: Las líneas dentro de un bloque do deben alinearse.

-- wrong 
a = do codes <- something 
     let numberCodes = zip [1..4] codes 

-- right 
a = do codes <- something 
     let numberCodes = zip [1..4] codes 

Fix 2: Al utilizar let dentro de un bloque do, no utilice in.

-- wrong 
func = do 
    let x = 17 
    in print x 

-- right 
func = do 
    let x = 17 
    print x 

Fix 3: UsoforM_ (que devuelve (), nula alias) en lugar de forM (que devuelve una lista).

codes <- forM [1..4] func... -- returns a list 
forM_ numberCodes $ ...  -- discards list, returns() 

Así podría forM_ (casi) escribirse así:

forM_ xs f = do forM xs f 
       return() 

Modificación de importancia menor: que no es necesario return aquí:

do func1 
    x <- func2 
    return x 

Usted puede cambiarlo a el equivalente,

do func1 
    func2 -- value of func2 is returned 
+0

¡Guau ... gracias! – agam

4

Líneas de sangrado excesivo en sus bloqueos. Además, no necesita un in para las declaraciones let en do -blocks.

Esto funciona para mí:

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] (\num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code) 
        let numberCodes = zip [1 .. 4] codes 
        forM numberCodes (\(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num) 

También puede estructurar de esta manera:

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] $ \num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code 
        let numberCodes = zip [1 .. 4] codes 
        forM numberCodes $ \(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num 

(lo que le permite evitar los paréntesis, como alternativa, poner el do al final de la \num -> y alinear declaraciones subsecuentes)

Cuestiones relacionadas