opciones - let in haskell




Haskell donde la sintaxis de la cláusula dentro de un bloque do (2)

¿No debería estar en su where al final de la función?

Me gusta esto:

function aList aValue = do
    mapM_ func aList
    return aValue
    where func x = x + 1

Estoy tratando de refactorizar una mapM_ función mapM_ dentro de un bloque do en Haskell. Me gustaría extraer la lambda a una función con nombre (localmente) para hacer que el código sea más legible.

Mi código originalmente se ve así:

do
  -- ...
  mapM_ (\x -> x + 1) aList

  return aValue

Me gustaría cambiarlo a

do
  -- ...
  mapM_ func aList
    where func x = x + 1

  return aValue

pero estoy recibiendo un error de sintaxis en la línea de return aValue . Mi lambda real es más complicada :-), pero la probé con esta misma lambda para asegurarme de que no era un problema en el código lambda.

¿Cómo puedo reescribir este código? ¿Debo usar let ... in lugar?


Hay tres formas similares (pero distintas) de definir cosas aquí:

  • Puede adjuntar las cláusulas where después de ciertas definiciones, principalmente enlaces de estilo de ecuación. Así que podría poner uno al final de su función, o después de algo definido con let o una cláusula circundante where .

  • Por otro lado, let x = ... in ... es una expresión que se evalúa en la parte posterior in , que es el único lugar en el let se puede ver el contenido después de let .

  • Dentro de un bloque do , debido a que ya hay un anidado implícito de alcance (las cosas son visibles después de que se definieron por primera vez), puede usar solo let x = ... solo. Esto es realmente lo mismo que en la forma anterior: el resto del bloque do después de let es efectivamente la parte in ...

Si desea una definición local que use algo definido dentro del bloque do , su única opción es la tercera (o pasar el otro valor (es) como argumento (s)). Sin embargo, para un ayudante independiente funciona como su ejemplo, cualquier estilo funciona. Aquí está tu ejemplo, para demostrar cada uno:

El primer estilo, donde func es visible en cualquier parte de foo , incluyendo cualquier otra cosa definida en la cláusula where :

foo = do ...
         mapM_ func aList
         ...
         return aValue
  where func x = x + 1

El segundo estilo, donde func solo es visible dentro de la expresión let , que en este caso es el bloque do completo:

foo = let func x = x + 1 
      in do 
         ...
         mapM_ func aList
         ...
         return aValue

Y el tercer estilo, definiéndolo dentro del bloque do . En este caso, func solo es visible después de let ; En la primera ... aún no se ha definido.

foo = do ...
         let func x = x + 1
         mapM_ func aList
         ...
         return aValue

Ah, y por si acaso, ya que let ... in ... es una expresión, también puede usarla en cualquier lugar donde tenga una expresión, para nombrar algunas definiciones locales. Así que aquí hay otro ejemplo:

foo = do ...
         let func x = x + 1 in mapM_ func aList
         ...
         return aValue

Como antes, func solo es visible dentro de la expresión let , que en este caso es la única expresión posterior a ella, en ninguna otra parte.





where-clause