2009-10-27 11 views
8

Come posso creare una lista pigra che rappresenta una sequenza di numeri raddoppiati? Esempio:Ocaml: Lazy Lists

1 2 4 8 16 32 
+1

Intendi qualche particolare implementazione di liste pigre, o solo il concetto generale? Inoltre, hai effettivamente bisogno di _lists_ pigri (dove i valori, una volta calcolati, sono memoizzati), o vuoi davvero un flusso (dove i valori non sono memoizzati e che possono quindi essere letti solo una volta)? –

+0

Sto cercando un flusso. –

risposta

9

La grande mente blog affrancato ha un grande articolo su questo argomento:

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

Si può anche verificare http://batteries.forge.ocamlcore.org/doc.preview%3Abatteries-beta1/html/api/Lazy%5Flist.html

che è la libreria standard per affrontare questo .

Questa domanda è molto simile a questa domanda:

What OCaml libraries are there for lazy list handling?

+0

Il primo collegamento non funziona più, hanno spostato l'host? – Oleg

+0

@Oleg si presenta come il dominio scaduto. Tale è la vita su internet. Questa risposta ha quasi 8 anni :) – chollida

+0

La libreria Batterie ora ha [tre diversi tipi di sequenza più o meno pigri] (https://github.com/ocaml-batteries-team/batteries-included/wiki/ListTypes), con diverse proprietà. – Mars

13

Uso torrenti:

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

o

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

Utilizzando un tipo personalizzato 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

Se si vuole farlo a mano, direi che devi opzioni principali:

  • Utilizzare un tipo personalizzato lazy_list, come ephemient detto (eccetto la sua soluzione è un po 'rotto) :

    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 
    
  • utilizzare una specie di tonfo (come la cosa utilizzato per implementare la valutazione pigra in una lingua che non lo supporta). Definisci il tuo elenco come una funzione unit -> 'a che dice come ottenere l'elemento successivo da quello corrente (non è necessario utilizzare flussi per questo). Ad esempio, per definire l'elenco di tutti i numeri interi naturali, si può fare

    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) 
    

    Il se lo fai

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

    si otterrà il seguente output:

    0 
    1 
    2 
    
+0

Quale parte del mio 'lazy_list' è rotta? Non l'ho provato quando lo stavo scrivendo, e ho sicuramente più familiarità con Haskell e SML rispetto a OCaml, ma l'ho testato proprio ora e funziona, su OCaml 3.11.1. Gli stream sono principalmente perché OP ha aggiunto un commento alla domanda che chiede flussi. – ephemient

+0

Woops, hai ragione, ho davvero * veramente * letto male ... Inoltre non ho visto il commento sull'utilizzo degli stream. La prossima volta mi metterò gli occhiali: s. – jdb

3

Inoltre, esiste un modulo elenco pigro chiamato Cf_seq nella mia Fondazione core OCaml Network Application Environment. In effetti, ho scritto un'intera passerella di strutture dati funzionali. È tutto disponibile con una licenza BSD a 2 clausole. Godere.

Aggiornamento: il codice è stato rinominato "Oni" ed è ora ospitato su BitBucket. Puoi anche usare il pacchetto GODI per questo.