Генерация последовательных членов бесконечного списка - PullRequest
2 голосов
/ 16 декабря 2010

У меня есть бесконечный список сущностей, сгенерированный таким образом:

entities =
  let f x = x ++ "'" 
  in "x" : "y" : "z" : map f entities

Я хотел бы определить функцию, которая возвращает новую сущность при каждом вызове.Например:

> nextEntity
x
> nextEntity
y
.
.
.

Полагаю, это место для Государственной монады, но я буду благодарен за указатели.

Подводный итог.вам нужны именованные переменные для ваших сущностей.«Джон любит Мэри» нужны две переменные (одна для Джона и одна для Мэри), «Джон дает Мэри книгу» нужны три переменные (Джон, Мэри, книга) и т. Д. Мне нужен здесь метод генерации новогоимя переменной для каждой «вещи», с которой я сталкиваюсь при обработке предложений.

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

Ответы [ 3 ]

5 голосов
/ 16 декабря 2010

Я хотел бы определить функцию, которая возвращает новую сущность при каждом вызове. Как это:

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

Полагаю, это место для Государственной монады,

Да, действительно так. Монада состояний представляет собой вычисление с некоторым скрытым состоянием, которое вы можете изменить. Используя конструкцию do, вы можете комбинировать вычисления с сохранением состояния с более крупными, которые имеют общее состояние. В частности, каждое вычисление просто передает новое состояние последовательным.

Использование довольно простое.

nextEntity :: State [a] a
nextEntity = do 
  entity:rest <- get
  put rest
  return entity

test = do
   e1 <- nextEntity
   e2 <- nextEntity
   e3 <- nextEntity
   return [e1, e2, e3]

res = fst $ runState test entities
4 голосов
/ 16 декабря 2010

Для того, чтобы функция могла это сделать, она должна иметь какое-то состояние, которое она меняет при вызове, чего нельзя сделать с чистыми функциями Haskell. Вы можете использовать Государственную монаду, но я думаю, что есть лучшие способы решения вашей проблемы, какой бы она ни была.

Вот как это можно сделать внутри Государственной монады

nextEntity :: State Int String
nextEntity = do
               s <- get
               put (s+1)
               return (entities !! s)

Который, чем вы можете использовать его в расчете внутри государственной монады, как это:

someCalculation = do
                    s1 <- nextEntity
                    s2 <- nextEntity
                    (do something with them)

чтобы разные значения связывались с s1 и s2. Но все это следует рассматривать только как упражнение для государственной монады, потому что я уверен, что есть лучшее решение для того, что вы пытаетесь сделать.

1 голос
/ 16 декабря 2010

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

nextEntity :: State [a] a
nextEntity = modify tail >> gets head

И мы можем написать функцию, которая выдаст вам первые 100 элементов, например:

test = sequence (replicate 100 nextEntity)

Напечатайте их так:

main = sequence_ . map print . evalState test $ entities
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...