Простой пример зависимого типа в Lean4

Вопрос или проблема

import Lean1.Basic

structure ArrayN (n : Nat) (α : Type) where
  array : { array : Array α // array.size = n }

class Hash (HashType: Type) where
  hashSize: Nat
  hash: x -> ArrayN (hashSize) UInt8

structure Private (Key: Type) (HashType: Type) [Hash HashType] where
  keys: ArrayN (Hash.hashSize HashType) Key

structure Public (HashType: Type) [Hash HashType] where
  hashes:
    let n := Hash.hashSize HashType
    ArrayN n (ArrayN n UInt8)

def Public.fromPrivate {K: Type} {HashType: Type} [Hash HashType] (priv: Private K HashType): Public HashType := {
  hashes := priv.keys.array.map (λ key => hash key)
}

Код выше дает

недопустимое поле 'map', окружение не содержит 'Subtype.map'
  priv.keys.array
имеет тип
  { array // array.size = Hash.hashSize HashType }

У меня небольшая проблема с работой с зависимыми типами. Как мне поступить? Я знаю, что мне нужно получить доступ к внутреннему Array из ArrayN, чтобы у него был .map, но я не знаю как.

Также, вероятно, мне нужно будет доказать, что возвращаемый результат имеет тип Public, но я тоже не знаю как.

Ответ или решение

Пример зависимого типа в Lean4: Решение проблемы с ArrayN и доступом к полям

В Lean4, работа с зависимыми типами может быть немного запутанной, особенно для тех, кто только начинает исследовать эту область. В данном ответе я помогу разобраться с ошибкой, связанной с использованием типа ArrayN и доступом к его внутреннему массиву в контексте вашего вопроса.

Понимание ошибки

Ошибка, с которой вы столкнулись, связана с тем, что вы пытаетесь применить метод .map к полю array структуры ArrayN, которая сама по себе является зависимым типом. В Lean4 доступ к полям этих типов требует более явного указания типа, поскольку у вас нет прямого доступа к массиву без учета условий размера, определенного в зависимости n.

Решение проблемы

Чтобы использовать метод .map для внутреннего массива, нужно немного изменить вашу функцию Public.fromPrivate. Вместо того чтобы пытаться вызвать map напрямую на priv.keys.array, вам нужно извлечь массив и тогда применить .map.

Вот исправленная версия вашей функции:

def Public.fromPrivate {K: Type} {HashType: Type} [Hash HashType] (priv: Private K HashType): Public HashType := {
  hashes := let innerArray := priv.keys.array.get -- Извлекаем внутренний массив
              innerArray.map (λ key => Hash.hash key) -- Применяем map к внутреннему массиву
}

Здесь мы используем let innerArray := priv.keys.array.get, чтобы получить доступ к внутреннему массиву типа Array α, и только после этого вызываем map, передавая функцию хеширования.

Доказательство, что результат соответствует типу Public

Теперь, когда мы правильно извлекли внутренний массив и применили к нему метод map, структура Public будет инициализирована корректно. Доказательство того, что возвращаемый результат соответствует типу Public, будет автоматическим в Lean, основанным на том, что вы соблюдаете все предшествующие определения типов и свойства классов. Когда вы вызываете конструктор Public, будет проверено, что hashes имеет правильный тип, благодаря зависимым типам.

Заключение

Работа с зависимыми типами в Lean4 требует внимательного обращения с типами и явного доступа к полям. Извлечение внутреннего массива из зависимого типа, такого как ArrayN, делает вашу функцию fromPrivate правильной и позволяет вам избежать ошибок компиляции.

Теперь вы можете успешно использовать хеши для создания Public типа из Private, и при этом ваши виды остаются корректными. Если у вас есть дополнительные вопросы или вам нужна дополнительная помощь в Lean4, не стесняйтесь обращаться!

Оцените материал
Добавить комментарий

Капча загружается...