Pregunta

Me escribió una función Haskell que calcula el factorial de cada número en una lista dada y lo imprime a la pantalla.

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)

La función funciona, pero me parece que la tercera línea un poco confuso. ¿Por qué el compilador (GHC) no ha informado de un error en él ya que no hay "hacer" antes de la función "putStrLn" (cuasi?)? Si omito "hacer" de la cuarta línea, se producirá un error como se esperaba.

Soy bastante nuevo en Haskell y sus formas, así que me Por favor, perdón si he dicho algo demasiado tonto.

¿Fue útil?

Solución

do putStrLn ((show.fact.head) list)
   factPrint (tail list)

En realidad, es otra manera de escribir

putStrLn ((show.fact.head) list) >> factPrint (tail list)

que, a su vez, significa

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)

La notación do es una manera conveniente de encadenar estas mónadas juntos, sin esta otra sintaxis feo.

Si usted tiene solamente una declaración dentro del do, entonces usted no está de encordar nada juntos, y el do es redundante.

Otros consejos

Si usted es nuevo en Haskell, piensa en do como similar a los apoyos requeridos después if en un C-como el lenguaje:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}

do funciona de la misma manera en Haskell.


Tal vez ayudaría a mirar el tipo de factPrint, y luego a refactor patrón de uso de juego:

factPrint :: [Int] -> IO ()
factPrint [] = putStrLn ""
factPrint list = do
  putStrLn (show.fact.head) list
  factPrint (tail list)

Por lo tanto, si factPrint vuelve IO (), y el tipo de putStrLn "" es IO (), entonces es perfectamente legal para factPrint [] al igual putStrLn "". No se requiere do - de hecho, sólo podría decir factPrint [] = return () si no desea que el salto de línea final

.

do se utiliza para atar múltiples expresiones monádicos juntos. No tiene ningún efecto cuando seguido por sólo una única expresión.

En el caso de ser bien formado sólo es necesario que el entonces cláusula y la cláusula-demás tienen el mismo tipo. Dado que ambas cláusulas tienen el tipo IO () este es el caso.

La DO palabra clave se utiliza para la secuenciación, un if-then-else en Haskell no tiene que contener una do en absoluto si cada rama es una sola instrucción por ejemplo.

if a
  then b
  else c

Se necesita el do en su ejemplo como se Secuenciando dos operaciones en su sucursal más. Si se omite el do entonces la declaración factPrint(tail list) se considera que no sea parte de la función y por lo tanto el compilador se queja como se le encontró una declaración inesperada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top