2009-10-27 15 views
8

¿Cómo puedo hacer que una lista perezosa represente una secuencia de números duplicados? Ejemplo:Ocaml: Lazy Lists

1 2 4 8 16 32 
+1

¿Te refieres a alguna implementación particular de listas perezosas, o simplemente al concepto general? Además, ¿realmente necesita _listas_ perezosas (donde los valores, una vez calculados, son memorables), o realmente solo quiere una secuencia (donde los valores no se memoran, y que, por lo tanto, solo se pueden leer una vez)? –

+0

Estoy buscando una transmisión. –

Respuesta

9

La gran mente el blog con derecho a voto tiene un gran artículo sobre este tema:

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

también se puede comprobar a cabo http://batteries.forge.ocamlcore.org/doc.preview%3Abatteries-beta1/html/api/Lazy%5Flist.html

que es la biblioteca estándar para hacer frente a esta .

Esta pregunta también es muy similar a esta pregunta:

What OCaml libraries are there for lazy list handling?

+0

El primer enlace ya no funciona, ¿movieron el host? – Oleg

+0

@Oleg parece que el dominio ha caducado. Tal es la vida en internet. Esta respuesta ya tiene casi 8 años :) – chollida

+0

La biblioteca de baterías ahora tiene [tres tipos de secuencias más o menos perezosas] (https://github.com/ocaml-batteries-team/batteries-included/wiki/ListTypes), con diferentes propiedades. – Mars

13

Uso de corrientes:

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) 

El uso de un tipo personalizado 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

Si desea hacerlo a mano, diría que tiene que opciones principales:

  • Usar un tipo personalizado lazy_list, como dijo ephemient (excepto su solución es un poco roto) :

    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 
    
  • usar un tipo de procesador (como la cosa utilizado para implementar la evaluación perezosa en un idioma que no lo soporta). Usted define su lista como una función unit -> 'a que dice cómo obtener el siguiente elemento del actual (no es necesario usar flujos para eso). Por ejemplo, para definir la lista de todos los enteros naturales, que puede hacer

    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) 
    

    El si lo hace

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

    obtendrá el siguiente resultado:

    0 
    1 
    2 
    
+0

¿Qué parte de mi 'lazy_list' está rota? No lo probé cuando estaba escribiéndolo, y definitivamente estoy más familiarizado con Haskell y SML que con OCaml, pero lo probé hace un momento y funciona en OCaml 3.11.1. Streams se debe principalmente a que OP agregó un comentario a la pregunta que solicita transmisiones. – ephemient

+0

Woops, tienes razón, realmente * realmente * leí mal ... Además, no vi el comentario sobre el uso de transmisiones. La próxima vez me pondré los lentes: s. – jdb

3

Además, hay un módulo de lista diferida llamado Cf_seq en mi OCaml Network Application Environment Core Foundation. De hecho, escribí toda una serie de estructuras de datos funcionales. Todo está disponible bajo una licencia BSD de 2 cláusulas. Disfrutar.

Actualización: el código ha cambiado de nombre "Oni" y ahora está alojado en BitBucket. También puede usar el paquete GODI para él.