Создайте последовательность из функции - PullRequest
0 голосов
/ 16 мая 2018

Я написал эти функции, чтобы построить последовательность из функции, у которой возникла ошибка переполнения стека при тестировании

let rec from_fun f ()=
  match f () with
  | None -> Nil
  | Some e -> Cons(e, from_fun f)
from_fun (fun () -> let x = 0 in if x<10 then Some (x+1) else None)

спасибо

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Используемая вами переменная x является локальной для анонимной функции, которую вы используете.В результате функция всегда возвращает Some 1.Вероятно, вы хотели, чтобы функция принимала аргумент:

let rec from_fun f n =
    match f n with
    | None -> Nil
    | Some e -> Cons(e, from_fun f e)

let seq = from_fun (fun x -> if x<10 then Some (x+1) else None) 0

РЕДАКТИРОВАТЬ: Вот решение с соответствующей сигнатурой типа:

let rec from_fun f () =
    match f () with
    | None -> Nil
    | Some e -> Cons(e, from_fun f ())

let x = ref 0

let seq = from_fun
    (fun () ->
        let v = !x in
        if v < 10
        then begin
            x := v + 1;
            Some v
        end
        else None)
    ()

Стоит отметить, чтоиз-за побочных эффектов вам придется повторно инициализировать x перед созданием новой последовательности.Аргумент unit, передаваемый параметру в from_fun, не нужен, его можно удалить.

0 голосов
/ 16 мая 2018

Вот пример генератора:

let range_generator from below step =
  let counter = ref from
  in fun () ->
       if (!counter < below)
       then (let result = (Some !counter) in
             counter := !counter + step;
             result)
       else None

Например, вызов range_generator 0 10 2 возвращает замыкание по внутренней изменяемой переменной counter, которая генерирует все натуральные четные числа ниже 10:

# let gen = range_generator 0 10 2;;
val gen : unit -> int option = <fun>

Каждый вызов gen возможно изменяет внутренний счетчик:

# gen();;
- : int option = Some 0
# gen();;
- : int option = Some 2
# gen();;
- : int option = Some 4
# gen();;
- : int option = Some 6
# gen();;
- : int option = Some 8
# gen();;
- : int option = None
# gen();;
- : int option = None

С вашей функцией:

# from_fun (range_generator 0 5 1);;
- : int list = [0; 1; 2; 3; 4]
0 голосов
/ 16 мая 2018

Ваша функция всегда возвращает Some 1.Он никогда не возвращается None.Таким образом, последовательность бесконечно длинна, и стек переполняется при ее создании.

Если вы хотите, чтобы функция возвращала разные значения при вызове, вы можете сделать две вещи.Во-первых, вы можете передать ему разные параметры.Это невозможно для вашего дизайна from_fun - параметр функции всегда ().Во-вторых, ваша функция может быть нечистой.Т.е. функция может поддерживать некое изменяемое состояние.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...