Ocaml List: реализовать функции добавления и отображения

Вы можете делать то, что вам нужно сделать, но оно не документировано:

>>> import json
>>> json.encoder.FLOAT_REPR = lambda f: ("%.2f" % f)
>>> json.dumps([23.67, 23.97, 23.87])
'[23.67, 23.97, 23.87]'
11
задан starblue 10 January 2009 в 12:31
поделиться

3 ответа

let rec append l1 l2 = 
    match l1 () with
        Nil -> l2 | 
        (Cons (a, l)) -> fun () -> (Cons (a, append l l2));;

let rec map f l =
    fun () -> 
        match l () with
            Nil -> Nil | 
            (Cons (a, r)) -> fun () -> (Cons (f a, map f r));;

Основная идея об этой реализации ленивых списков состоит в том, что каждое вычисление инкапсулируется в функции (технический термин является закрытием) через забаву ()-> x. Выражение x затем только оценено, когда к функции относятся () (стоимость единицы, которая не содержит информации).

7
ответ дан 3 December 2019 в 08:05
поделиться

Это могло бы помочь отметить, что функциональные закрытия чрезвычайно эквивалентны ленивым значениям:

lazy n : 'a Lazy.t    <=>    (fun () -> n) : unit -> 'a
force x : 'a          <=>    x () : 'a

Так тип 'a llist эквивалентно

type 'a llist = 'a cell Lazy.t

т.е. ленивое значение ячейки.

Реализация Map могла бы иметь больше смысла с точки зрения вышеупомянутого определения

let rec map f lst =
  match force lst with
    | Nil -> lazy Nil
    | Cons (hd,tl) -> lazy (Cons (f hd, map f tl))

Перевод того назад в закрытия:

let rec map f lst =
  match lst () with
    | Nil -> (fun () -> Nil)
    | Cons (hd,tl) -> (fun () -> Cons (f hd, map f tl))

Так же с добавляют

let rec append a b =
  match force a with
    | Nil -> b
    | Cons (hd,tl) -> lazy (Cons (hd, append tl b))

становится

let rec append a b =
  match a () with
    | Nil -> b
    | Cons (hd,tl) -> (fun () -> Cons (hd, append tl b))

Я обычно предпочитаю использовать lazy синтаксис, так как это делает это более ясным, что продолжается.

Обратите внимание, также, что ленивая приостановка и закрытие не точно эквивалентны. Например,

let x = lazy (print_endline "foo") in
  force x;
  force x

печать

foo

тогда как

let x = fun () -> print_endline "foo" in
  x ();
  x ()

печать

foo
foo

Различие - это force вычисляет значение выражения точно однажды.

7
ответ дан 3 December 2019 в 08:05
поделиться

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

1
ответ дан 3 December 2019 в 08:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: