Лучший способ написать конструкторы как функции в Agda

У меня есть список

data List (X : Set) : Set where
  <>   : List X
  _,_  : X -> List X -> List X

определение равенства

data _==_ {l}{X : Set l}(x : X) : X -> Set l where
  refl : x == x

и конгруэнтность

cong : forall {k l}{X : Set k}{Y : Set l}(f : X -> Y){x y} -> x == y -> f x == f y
cong f refl = refl

Я пытаюсь доказать

propFlatten2 : {X : Set } ( xs0 : List X ) (x : X)  (xs1 : List X) (xs2 : List X)
              -> ( xs0 ++ x , xs1 ) ++ xs2  ==  xs0 ++ (x , xs1 ++ xs2 )
propFlatten2 <> x xs1 xs2 = refl
propFlatten2 (x , xs0) x₁ xs1 xs2 =   cong (λ l -> x , l) {!!}

Есть ли лучший способ использовать непосредственно конструктор _,_ кроме как через лямбду в последней строке?

1 ответ

Решение

У Agda нет специального синтаксиса для частичного применения операторов. Однако вы можете использовать операторы в их обычной префиксной версии:

x + y = _+_ x y

Это удобно, когда вам нужно частично применить крайний левый аргумент (ы):

_+_ 1 = λ x → 1 + x

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

flip f x y = f y x  -- Type omitted for brevity.

А потом просто flip аргументы _+_:

flip _+_ 1 = λ x → x + 1

Иногда вы найдете операторов, единственной целью которых является сделать код немного лучше. Лучший пример, который я могу придумать, это, вероятно, Data.Product.,_, Когда вы пишете зависимую пару (Data.Product.Σ), иногда первая часть пары может быть заполнена автоматически. Вместо того чтобы писать:

_ , x

Вы можете просто написать:

, x

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

Другие вопросы по тегам