在精益中解决 "diamond inheritance" class

Resolving a "diamond inheritance" class in lean

对于精益,我有一个非常基本的循环结构。我为岩浆构造了一个 class,为准群(抵消岩浆)构造了一个 class,为单位岩浆构造了一个 class。从那里开始,环就是既是准群又是单位岩浆的东西。

在 Haskell 中看起来像

class Magma a where
  add :: a -> a -> a

class Magma a => Unital a where
  unit :: a

class Magma a => Quasigroup a where
  left_div :: a -> a -> a
  right_div :: a -> a -> a

class (Quasigroup a, Unital a) => Loop a

所以我试着把它翻译成精益:

universe u

class magma (α : Type u) :=
  ( add : α → α → α )

class unital (α : Type u) extends magma α :=
  ( unit : α )
  ( left_id : ∀ a : α, add unit a = a )
  ( right_id : ∀ a : α, add a unit = a )

class quasigroup (α : Type u) extends magma α :=
  ( left_div : α → α → α )
  ( right_div : α → α → α )
  ( left_cancel : ∀ a b : α, add a (left_div a b) = b )
  ( right_cancel : ∀ a b : α, add (right_div b a) a = b )

class loop (α : Type u) extends quasigroup α, unital α

但是 lean 抱怨说:

invalid 'structure' header, field 'to_magma' from 'unital' has already been declared

这很神秘,但如果我们尝试一下,就会发现这是类似于钻石继承的某种问题。它不喜欢我们从 loopmagma 的两条路径。

如何判断 lean 这些是相同的岩浆并解决这个问题?

在 Lean 3.35.1 上,您有几种可能的解决方案。对于类似 Haskell 的记录合并,有 old_structure_cmd:

universe u

class magma (α : Type u) :=
(add : α → α → α)

class unital (α : Type u) extends magma α :=
(unit : α)
(left_id : ∀ a : α, add unit a = a)
(right_id : ∀ a : α, add a unit = a)

class quasigroup (α : Type u) extends magma α :=
(left_div : α → α → α)
(right_div : α → α → α)
(left_cancel : ∀ a b : α, add a (left_div a b) = b)
(right_cancel : ∀ a b : α, add (right_div b a) a = b)

set_option old_structure_cmd true

class loop (α : Type u) extends quasigroup α, unital α.

这将如您所愿。然而,old_structure_cmd 的缺点是结构都被“扁平化”并变大了。 “新”方式是拥有结构的主要“主干”,并创建分支继承:

universe u

class magma (α : Type u) :=
(add : α → α → α)

class unital (α : Type u) extends magma α :=
(unit : α)
(left_id : ∀ a : α, add unit a = a)
(right_id : ∀ a : α, add a unit = a)

class quasigroup (α : Type u) extends magma α :=
(left_div : α → α → α)
(right_div : α → α → α)
(left_cancel : ∀ a b : α, add a (left_div a b) = b)
(right_cancel : ∀ a b : α, add (right_div b a) a = b)

class loop (α : Type u) extends quasigroup α :=
(unit : α)
(left_id : ∀ a : α, add unit a = a)
(right_id : ∀ a : α, add a unit = a)

instance loop.to_unital {α : Type u} [h : loop α] : unital α :=
{ ..h }