Действительно, вам нужно in
после первого идентификатора. Согласно справочному руководству (§1.2.12):
let ident := term1 in term2
denotes the local binding of term1
to the variable ident
in term2
.
Вам нужно несколько (вложенных) let ... in
выражений:
Definition split {A:Set} (lst:list A) :=
let fst := take (length lst/2) lst in
let snd := drop (length lst/2) lst in
(fst, snd).
Кстати, вы можете использовать firstn
и skipn
функции от стандарта библиотека (List
module) вместо take
и drop
:
Require Import Coq.Lists.List.
Import ListNotations.
Compute firstn 3 [1;2;3;4;5]. (* Result: [1;2;3] *)
Compute skipn 3 [1;2;3;4;5]. (* Result: [4;5] *)
Это (и немного рефакторинга) приводит к следующему определению split
(я переименовал его, чтобы избежать затенения стандартной функции split
):
Definition split_in_half {A:Set} (lst:list A) :=
let l2 := Nat.div2 (length lst) in
(firstn l2 lst, skipn l2 lst).
Compute split_in_half [1;2;3;4;5]. (* Result: ([1; 2], [3; 4; 5]) *)
Кстати, он по-прежнему оставляет много места для если вас беспокоит несколько проходов по списку ввода. Который мог бы быть, если вы планируете делать извлечение, например. в OCaml.
Удивительный ответ, спасибо! Я только определяю свое собственное, чтобы овладеть языком :) – Langston
Спасибо :) Я также могу предложить посмотреть лемм 'firstn_skipn' и' firstn_length' (в модуле «Список»), которые суммируют и гарантируют (!) основные свойства соответствующих функций. –