2009-10-27 3 views
8

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

1 2 4 8 16 32 
+1

Вы имеете в виду конкретную реализацию ленивых списков или просто общую концепцию? Кроме того, вам на самом деле нужен ленивый _lists_ (где значения, после вычисления, запоминаются), или вам просто нужен поток (где значения не сохраняются в памяти, и поэтому их можно прочитать только один раз)? –

+0

Я ищу поток. –

ответ

9

Великий блог цензовая ум имеет большую статью по этой теме:

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

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

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

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

What OCaml libraries are there for lazy list handling?

+0

Первая ссылка больше не работает, они перемещают хост? – Oleg

+0

@Oleg выглядит как домен истек. Такова жизнь в Интернете. Этот ответ почти 8 лет сейчас :) – chollida

+0

В библиотеке Batteries теперь есть [три разных более или менее ленивых типа последовательности] (https://github.com/ocaml-batteries-team/batteries-included/wiki/ListTypes), с различными свойствами. – Mars

13

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

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

или

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))) 
1

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

  • использовать тип пользовательского 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 
    
+0

Какая часть моего 'lazy_list' нарушена? Я не тестировал его, когда писал его, и я определенно больше знаком с Haskell и SML, чем с OCaml, но я тестировал его только сейчас, и он работает, на OCaml 3.11.1. Потоки в основном потому, что OP добавил комментарий к вопросу, запрашивающему потоки. – ephemient

+0

Woops, вы правы, я действительно * действительно * неправильно читал это ... Плюс я не видел комментариев об использовании потоков. В следующий раз я надену очки: s. – jdb

3

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

Обновление: код был переименован в «Oni», и теперь он размещен в BitBucket. Вы также можете использовать пакет GODI.