Haskell: ¿Puedo usar una cláusula where después de un bloque con los operadores bind (>> =)?

StackOverflow https://stackoverflow.com/questions/1156954

  •  18-09-2019
  •  | 
  •  

Pregunta

Tengo una pregunta muy simple. Me gustaría utilizar una cláusula where después de un bloque de código que utiliza operadores se unen pero me da un error de compilación.

Este es un ejemplo sencillo:

main =
    putStrLn "where clause test:" >>
    return [1..10] >>= \list ->
    print list'
        where list' = reverse list -- test1.hs:5:28: Not in scope: `list'

Puedo utilizar una cláusula let para la lista' como en

main =
    putStrLn "where clause test:" >>
    return [1..10] >>= \list ->
    let list' = reverse list -- works of course
    in print list'

pero realmente me gustaría que si podía usar una cláusula where ...

También probé con la notación do

main = do
    putStrLn "where clause test:"
    list <- return [1..10]
    print list'
        where list' = reverse list --test3.hs:5:30: Not in scope: `list'

El mismo problema. ¿Puedo utilizar una cláusula where en estas circunstancias?

¿Fue útil?

Solución

Como ephemient explica, no se puede utilizar where cláusulas de la forma de hacer.

El error se debe a que en este código:

main =
  return [1..10] >>= \list ->
  print list'
    where
      list' = reverse list

La cláusula where está unido a la función principal.

Aquí está la misma función con más paréntesis:

main = return [1..10] >>= (\list -> print list')
  where
    list' = reverse list

Creo que es bastante obvio por qué se obtiene el error "out of scope": La unión de list es más profundo de la expresión main, no es algo que la cláusula where puede alcanzar

.

Lo que suele hacer en esta situación (y me ha picado la misma cosa que un montón de veces). Simplemente presento una función y pasar el list como argumento.

main = do
  list <- return [1..10]
  let list' = f list
  print list'
  where
    f list = reverse list -- Consider renaming list,
                          -- or writing in point-free style

Por supuesto, imaginar su código real en la función f es mucho más que simplemente reverse y es por eso que desea que el interior de una cláusula where, en lugar de una unión let en línea. Si el código dentro de la función f es muy pequeño, que acababa de escribir dentro de la unión del let, y no iría a través de la sobrecarga de la introducción de una nueva función.

Otros consejos

Por lo que yo puedo decir, la cláusula where sólo se utiliza en fijaciones locales . La parte interior de un >> (=) Estado de unión no es una unión (dos diferentes tipos de fijaciones en esa frase) locales.

Comparar con esto:

main = f [1..10]

f list =
    putStrLn "where clause test:" >> print list'
        where list' = reverse list

Es posible que desee hacer referencia a la Haskell 98 sintaxis informe - no seguro de la cantidad de ayuda que sería.

Si estoy equivocado, alguien sin duda me corrija, pero estoy bastante seguro de que no se puede utilizar una cláusula where en absoluto en el estilo que has mostrado anteriormente. list nunca será en su alcance a una cláusula donde a menos que sea un parámetro a la función.

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