Ocaml: Ленивые списки

Как мне составить ленивый список, представляющий последовательность удваивающихся чисел? Пример:

1 2 4 8 16 32

person Nick Heiner    schedule 27.10.2009    source источник
comment
Вы имеете в виду какую-то конкретную реализацию ленивых списков или просто общую концепцию? Кроме того, вам действительно нужны ленивые списки (где значения, однажды вычисленные, запоминаются), или вам действительно просто нужен поток (где значения не запоминаются и поэтому могут быть прочитаны только один раз )?   -  person Pavel Minaev    schedule 27.10.2009


Ответы (4)


Использование потоков:

let f x = Stream.from (fun n -> Some (x * int_of_float (2.0 ** float_of_int n)))

or

let f x =
  let next = ref x in
    Stream.from (fun _ -> let y = !next in next := 2 * y ; Some y)

Используя собственный тип lazy_list:

type 'a lazy_list =
  | Nil
  | Cons of 'a * 'a lazy_list lazy_t
let rec f x = lazy (Cons (x, f (2*x)))
person ephemient    schedule 27.10.2009

В великом блоге с неограниченным умом есть отличная статья на эту тему:

http://enfranchisedmind.com/blog/posts/ocaml-lazy-lists-an-introduction/

Вы также можете проверить http://batteries.forge.ocamlcore.org/doc.preview%3Abatteries-beta1/html/api/Lazy%5Flist.html

которая является стандартной библиотекой для решения этой проблемы.

Этот вопрос также очень похож на этот вопрос:

Какие библиотеки OCaml существуют для ленивой обработки списков?

person chollida    schedule 27.10.2009
comment
Первая ссылка больше не работает, хост переместили? - person Oleg; 06.03.2017
comment
@Oleg похоже, что срок действия домена истек. Такова жизнь в Интернете. Этому ответу уже почти 8 лет :) - person chollida; 08.03.2017
comment
В библиотеке Batteries теперь есть три разных более или менее ленивых типа последовательностей, с разными свойствами. - person Mars; 20.01.2018
comment
Первая ссылка на archive.org: web.archive.org/web/20110415103938/www.enfranchisedmind.com/ - person Rich; 28.07.2020

Кроме того, в моем OCaml Network Application Environment Core Foundation есть модуль отложенного списка под названием Cf_seq. Фактически, я написал целый ряд функциональных структур данных. Все это доступно по лицензии BSD с двумя пунктами. Наслаждаться.

Обновление: код был переименован в "Oni" и теперь размещен на BitBucket. Вы также можете использовать для этого пакет GODI.

person james woodyatt    schedule 27.10.2009

Если вы хотите сделать это вручную, я бы сказал, что у вас есть основные варианты:

  • Используйте собственный тип lazy_list, как сказал ephemient (за исключением того, что его решение немного не работает):

    type 'a lazy_list =
        | Nil
        | Cons of 'a * 'a lazy_list
    
    let head = function
        | Nil -> failwith "Cannot extract head of empty list"
        | Cons (h, _) -> h
    
    let tail = function
        | Nil -> failwith "Cannot extract tail of empty list"
        | Cons (_, t) -> t
    
  • Используйте своего рода преобразователь (например, то, что используется для реализации ленивых вычислений на языке, который его не поддерживает). Вы определяете свой список как функцию unit -> 'a, которая говорит, как получить следующий элемент из текущего (нет необходимости использовать для этого потоки). Например, чтобы определить список всех натуральных целых чисел, вы можете сделать

    let make_lazy_list initial next =
        let lazy_list current () =
            let result = !current in
            current := (next !current); result
        in lazy_list (ref initial)
    
    let naturals = make_lazy_list 0 (function i -> i + 1)
    

    Если вы это сделаете

    print_int (naturals ());
    print_int (naturals ());
    print_int (naturals ())
    

    вы получите следующий результат:

    0
    1
    2
    
person jdb    schedule 27.10.2009
comment
Какая часть моего lazy_list сломана? Я не тестировал его, когда писал его, и я определенно более знаком с Haskell и SML, чем с OCaml, но я тестировал его только сейчас, и он работает на OCaml 3.11.1. Streams в основном потому, что OP добавил комментарий к вопросу о потоках. - person ephemient; 27.10.2009
comment
Woops, вы правы, я действительно действительно неправильно это прочитал ... Плюс я не видел комментария об использовании потоков. В следующий раз надену очки: s. - person jdb; 28.10.2009