Prefix_action, суффикс_action с последовательностями - PullRequest
0 голосов
/ 04 июня 2018

Я хочу написать функцию prefix_action с seq (соответственно суффикс_акция), вот код в BatEnum:

 let prefix_action f t =
  let full_action e =
    e.count <- (fun () -> t.count());
    e.next  <- (fun () -> t.next ());
    e.clone <- (fun () -> t.clone());
    f ()
  in
  let rec t' =
    {
      count = (fun () -> full_action t'; t.count() );
      next  = (fun () -> full_action t'; t.next()  );
      clone = (fun () -> full_action t'; t.clone() );
      fast  = t.fast
    } in t'

Я хочу знать, поскольку у нас нет клонов в последовательностях, я хочузнаете, как я должен рассмотреть клон в этих случаях (это использование последовательности), и если это так, как мы можем определить, сколько раз эта последовательность используется? Prefix_action Documentation

1 Ответ

0 голосов
/ 05 июня 2018

Последовательность, как она определена, не имеет функции клона только потому, что она «определена по умолчанию».

type 'a node =
|   Nil
|   Cons of 'a * 'a t
and 'a t = unit -> 'a node

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

let clone s = s

Теперь, если вы посмотрите на определение перечисления, вы заметите небольшое ключевое слово mutable:

type 'a t = { 
  mutable count : unit -> int;
  mutable next  : unit -> 'a;
  mutable clone : unit -> 'a t;
  mutable fast  : bool;
}

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

# let e1 = { fast = true; (* ... *) };;
val e1 : 'a t = {fast = true; (* ... *)}
# let e2 = clone e1;;
val e2 : 'a t = {fast = true; (* ... *)}
# e1.fast <- false;;
- : unit = ()
# e2;;
'a t = {fast = false; (* ... *)}

Вот почему им нужна функция clone.

Тактеперь вы можете реализовать свои функции, например prefix_action.

prefix_action f e будет вести себя как e, но гарантирует, что f () будет вызван ровно один раз перед текущим первым элементом e читается.

Проблема в этом "ровно один раз" .Я не уверен, что это значит, но допустим, что это означает, что если вы передадите последовательность в prefix_action f, а затем два раза в hd, то f будет выполнен только один раз (потому что если это означает что-то другоеэто не интересно).И теперь мы можем вернуться к этой истории «побочных эффектов».Ясно, что мы не можем реализовать prefix_action без них.Тип последовательности не содержит ни одного ключевого слова mutable, но содержит функции!Следовательно, мы можем включить наш побочный эффект в функцию.

let prefix_action : (unit -> unit) -> 'a t -> 'a t = fun f s ->
    let b = ref true in
    fun () -> (if !b then f (); b := false); s ()

Но теперь, когда у нас есть побочные эффекты, нам нужно переопределить clone.Из спецификации prefix_action:

Если клонируется prefix_action f e, f вызывается только один раз, во время клонирования.

Следовательно, наш clone:

let clone s = let _ = s (); s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...