Вопрос

Человек в Reddit привлек этот код к моему сведению:

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

Что происходит здесь, так это то, что у нас есть множество операций, с которыми мы можем делать что -то, например, обратное или получить его хвост или голову.

Потрясающий.

Что я хочу сделать, так это попасть в отдельные элементы и изменить их навсегда. Например, я хочу иметь возможность сделать что -то вроде этого:

ns !! 0

И получите что -то вроде [Print, 1], а затем измените последний элемент, скажем, 3.14, чтобы функция печатала 3.14.

Это вообще возможно в Haskell или я должен просто вернуться к Lisp?

Важное редактирование: я вроде как ошибался. Я понимаю, что мне нужно будет создать новый список. Можно ли получить аргументы функции, которая является частью списка? Я хочу, чтобы возможность составлять функции из их идентификаторов/аргументов, а также иметь возможность разбить функцию на идентификатор/аргумент, прежде чем она будет оцениваться.

Это было полезно?

Решение

Это немного сложнее, чем в LISP, но для метапреграммирования в Хаскелле вы можете использовать Шаблон Хаскелл.

Например, [|print 1|] будет переведен на

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

который имеет тип Q Exp (Цитата выражения).

Если вы хотите объединить свои собственные данные в цитату, [|print $(foo 3.14)|] выполнит foo 3.14 В время компиляции.

Другие советы

После того, как вы применили значение к функции, нет возможности вернуть его. Попробуйте обернуть функцию и ее аргумент в дата, который вы можете оценить или разложить в зависимости от ваших потребностей.

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

Выходы

1
2
3
1
4
9

Вы хотите мутировать список? Вы должны вернуться к LISP ;-)

Значения неизменны в Хаскелле. Haskell-Way-создать новый список, который эквивалентен старому списку, за исключением последнего элемента.

(Есть некоторые хитрости с участием Monads, где вы можете смоделировать изменяемые значения и указатели, но это, вероятно, не то, что вы хотите здесь.)

РЕДАКТИРОВАТЬ: Не совсем уверен, что я понимаю отредактированный вопрос, но вы можете обрабатывать функцию и аргументы отдельно как данные, а затем «применить» позже, например;

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

Как было сказано, Haskell Way - это просто создать новый список, но у вас могут быть изменяемые массивы в IO Monad с ioarray, если вы действительно хотите

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top