haskell macros lisp lazy-evaluation

(emulado) macros en haskell?



lisp lazy-evaluation (4)

Una persona en Reddit ha traído este código a mi atención:

main = do let ns = [print 1, print 2, print 3] sequence_ ns sequence_ $ reverse ns sequence_ $ tail ns ++ [head ns] head ns

Lo que está sucediendo aquí es que tenemos una serie de operaciones con las que podemos hacer cosas, como retroceder u obtener su cola o cabeza.

Increíble.

Lo que quiero hacer es meterme en elementos individuales y cambiarlos para siempre. Por ejemplo, quiero poder hacer algo como esto:

ns !! 0

y obtenga algo como [imprimir, 1] y luego cambie el último elemento a, digamos, 3.14 para que la función imprima 3.14.

¿Es posible en Haskell o debo volver a LISP?

UNA EDICIÓN IMPORTANTE: tipo de error. Entiendo que necesitaré crear una nueva lista. ¿Es posible obtener los argumentos de una función, que forma parte de una lista? Lo que quiero es la capacidad de componer funciones a partir de sus identificadores / argumentos y también poder dividir una función en identificador / argumento antes de que se evalúe.


Es un poco más complicado que en Lisp, pero para la metaprogramación en Haskell, puedes usar Template Haskell .

Por ejemplo, [|print 1|] será traducido a

return $ AppE (VarE $ mkName "print") (LitE $ IntegerL 1)

que tiene el tipo Q Exp (una cita de una expresión).

Si desea unir sus propios datos en una cotización, [|print $(foo 3.14)|] ejecutará foo 3.14 en tiempo de compilación.


Se ha dicho que la forma haskell es simplemente crear una nueva lista, pero puede tener arreglos mutables dentro de la mónada IO con IOArray si realmente desea

import Data.Array.IO seqArr_ arr = getElems arr>>=sequence_ main= do arr <- newListArray (0,2) [print 1,print 2,print 3] :: IO (IOArray Int (IO ())) seqArr_ arr -- prints 1 2 3 writeArray arr 2 (print 3.14) -- change the last element seqArr_ arr -- prints 1 2 3.14


Una vez que ha aplicado un valor a una función, no hay forma de recuperarlo. Intente ajustar la función y su argumento en un tipo de datos que pueda evaluar o descomponer según sus necesidades.

data App a b = App (a -> b) a runApp (App a b) = a b ns = [App print 1, App print 2, App print 3] main = do sequence_ $ map runApp ns let ns2 = [App fun (arg^2) | App fun arg <- ns] sequence_ $ map runApp ns2

Salidas

1 2 3 1 4 9


¿Quieres mutar la lista? Deberías volver a lisp ;-)

Los valores son inmutables en Haskell. Haskell-way es crear una nueva lista que es equivalente a la lista anterior, excepto el último elemento.

(Hay algunos trucos relacionados con mónadas donde puedes simular valores y punteros mutables, pero probablemente no sea lo que quieres aquí).

EDIT: No estoy totalmente seguro de entender la pregunta editada, pero puede manejar la función y el argumento por separado como datos y luego "aplicar" más tarde, por ejemplo;

do let ns = [(print, 1), (print, 2), (print, 3)] sequence_ $ map (/(f,a)->f a) ns