How to write a definition of the non-dependent product using Pi types in Lean? - dependent-type

I'm working through chapter 7 – Inductive Types of "Theorem Proving in Lean".
I'd like to know how to write the definition of dependent non-dependent product in a more expanded or "primitive" form.
It looks like the definition given in the tutorial automatically infers some detail:
inductive prod1 (α : Type u) (β : Type v)
| mk : α → β → prod1
Some experimentation allows to fill in the detail
inductive prod2 (α : Type u) (β : Type v) : Type (max u v)
| mk : α → β → prod2
However giving the definition in a fully expand form, using Pi types fails to typecheck:
inductive prod3 : Π (α : Type u) (β : Type v), Type (max u v)
| mk : α → β → prod3
What is the correct way to write prod3?
Finally, is the following definition equivalent to prod1 and prod2, i.e. can the type checker always infer the correct type universe for α and β?
inductive prod4 (α : Type) (β : Type)
| mk : α → β → prod4

First off, note that there is nothing dependent about your types. Dependent product is just another name for the Pi type itself (the Pi deriving from the usual mathematical notation for indexed products).
Your prod2 type is the correct maximally explicit version of prod1. In prod3, you changed α and β from inductive parameters to indices, which as you noticed doesn't work out for universe-related reasons. In general, indices are used to define inductive type families as in section 7.7.
Finally, the atomic Type you used in prod4 is an abbreviation of Type 1. You can use Type* to have universe parameters inferred automatically.

Related

Type checking for Vectors in Idris

From REPL how does not ensures that the a list is indeed interpret as a vector instead?
For example if I type:
:t Vect
I get Vect : Nat -> Type -> Type which makes absolute sense, if I type
:t Vect 2
I get Vect : Type -> Type which makes again absolute sense. But I try now:
:t Vect 2 [1,2]
and get an error
Can't disambiguate since no name has a suitable type:
Prelude.List.::, Prelude.Stream.::, Data.Vect.::
I was hoping to see instead [1,2] : Vect 2 Int instead. What I am doing wrong? I also have issues when using the function the when trying to interpret a list as vector.
Any suggestion?
the : (a : Type) -> a -> a takes a type and a value of that type and returns that value. So if the target type cannot be inferred from context, like in the REPL, you can use the (Vect 2 Int) [1,2] to specify what you mean with [1,2].
(Vect 2 [1,2] tries to use the List, Stream or Vect [1,2] as the argument in Vect 2 : Type -> Type. But unlike e.g. Int, the list [1,2] is not a Type, so that throws you that error.)

Idris Dependent Pairs: Unexpected behavior between compiled program and REPL

When practicing using dependent pairs in Idris, I have encountered an unexpected difference in behavior between compiled programs and the REPL. The following datatype is what I am testing with:
(a : Type ** b : Type ** Arrow a b)
Which should represent some relation between type a and type b. Given an instance of the above, I would like to extract the "proof" term of the type. I can do this from the REPL with DPair.snd $ DPair.snd <some-instance> and everything works fine. However, if I try to make a function:
unwrap : (a ** b ** Arrow a b) -> Arrow a b
unwrap x = DPair.snd $ DPair.snd x
the program will compile, but will fail when I try to call it. The error message returned is
(input): No such variable b
Has anyone encountered this or knows of a solution?
What you want to achieve is not possible. If you look at the type of unwrap : (a1 : Type ** b1 : Type ** Arrow a b) -> Arrow a b you see that it uses a different datatype than (a : Type ** b : Type ** Arrow a b). That's because the arguments a, b are quantified beforehand - setting the resulting type (which is also the difference to the REPL case; there you aren't bound to the arguments). So with :set showimplicit it is
Main.unwrap : {b : Type} -> {a : Type} ->
(a1 : Type ** b1 : Type ** Main.Arrow a b) ->
Main.Arrow a b
That's the thing about dependent pairs, you can't restrict them easily. Take a look at Vect.filter : (elem -> Bool) -> Vect len elem -> (p : Nat ** Vect p elem) - if we had a function like unwrap : (p : Nat ** Vect p elem) -> Vect p elem, we wouldn't need dependent pair in the first place.
Instead, a function that would call unwrap would need to inspect p and then handle the Vect accordingly. Sadly, we can't easily inspect types (at least if you want to generalize for all types). So your best bet is: don't use dependent types here.
I realise I'm a year and a half late, but... This absolutely is possible! You just need to remember that the type a ** P is just syntactic sugar for DPair a (\x => P a); in the latter form, nothing special is going on whatsoever and so you can use your a and b just like you'd expect. We can also gain insight from how DPair.snd is typed in the standard library:
Idris> :t DPair.snd
snd : (x : DPair a P) -> P (fst x)
So, to extract the a-value from our pair, we simply call fst on that pair. How intuitive! (fst itself simply has the type DPair a P -> a). To get the b-value, which is the first value of the second part of our pair, we call fst . snd on the outermost pair. Therefore, your function should look like:
unwrap : (x : DPair a (DPair b . Arrow)) -> Arrow (fst x) (snd $ fst x)
unwrap x = snd (snd x)
(or, equivalently:)
unwrap : (x : DPair a (\theA => DPair b (\theB => Arrow theA theB))) -> ...
For whatever reason, unwrap = DPair.snd . DPair.snd doesn't work... but that's not too much of an issue.

In Lean, is it possible to use decidable_linear_order with a user defined equality relation?

Lean comes with a decidable_linear_order typeclass containing useful lemmas about an ordering and its relation to equality, such as:
lemma eq_or_lt_of_not_lt [decidable_linear_order α] {a b : α} (h : ¬ a < b) : a = b ∨ b < a
The equalities in these orderings are all expressed in terms of =:
inductive eq {α : Sort u} (a : α) : α → Prop
| refl : eq a
I was wondering whether it would be possible to somehow extend this class (and its superclasses) to work with an arbitrary used defined equality relation R: α → α → Prop that was reflexive, symmetric and transitive, or would this only be possible by rewriting all the relevant lemmas and their proofs to use R instead of eq?
Since these classes are not parameterized by the equality relation, you would indeed have to reimplement them (perhaps metaprogramming may be of help for that). Alternatively, because you have an equivalence relation, you could define your order on the quotient type and so keep using eq.

Example of a `Type 1` that is neither `Type` nor an inhabitant of `Type`

What is an example of an inhabitant of Type 1 that is neither Type nor an inhabitant of Type? I wasn't able to come up with anything while exploring in the Idris REPL.
To be more precise, I'm looking for some x other than Type that yields the following:
Idris> :t x
x : Type 1
I'm not a type theory specialist, but here is my understanding. In the Idris tutorial there is a section 12.8 Cumulativity. It says that there is an internal hierarchy of type universes:
Type : Type 1 : Type 2 : Type 3 : ...
And for any x : Type n implies x : Type m for any m > n. There is also an example demonstrating how it prevents possible cycles in the type inference.
But I think that this hierarchy is only for internal use and there is no possibility to create a value of Type (n+1) which is not in Type n.
See also articles in nLab about universes in type theory and about type of types.
Maybe this issue in the idris-dev repository can be useful too. Edwin Brady refers there to the Design and Implementation paper (see section 3.2.2).
I'm not an Idris expert, but I'd expect that
Type -> Type
is also in Type 1.
I'd also expect
Nat -> Type
and if you're very lucky (not so sure about this one)
List Type
to be that large.
The idea is that you can do all type-building operations at every level. Each time you use types from one level as values, the types of those structures live one level up.

Equality testing without explicit proof that data constructors are injective

Is it possible to define a simple syntactic notion of equality (similar to what GHC might automatically derive as the Eq instance for a Haskell 98 type), without either explicitly proving that each data constructor is injective, or doing something analogous, such as defining the retraction of each constructor and using cong?
In other words, is it possible to exploit the injectivity of data constructors more directly, rather than having to introduce one auxiliary function per constructor?
The following uses the natural numbers as an example.
module Eq where
open import Function
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
data ℕ : Set where
zero : ℕ
suc : ℕ → ℕ
-- How to eliminate these injectivity proofs?
suc-injective : ∀ {n m} → suc n ≡ suc m → n ≡ m
suc-injective refl = refl
_≟_ : Decidable {A = ℕ} _≡_
zero ≟ suc _ = no (λ ())
suc _ ≟ zero = no (λ ())
zero ≟ zero = yes refl
suc n ≟ suc m with n ≟ m
suc n ≟ suc .n | yes refl = yes refl
... | no n≢m = no (n≢m ∘ suc-injective)
One could replace suc-injective by cong (λ { zero → zero ; (suc x) → x }), i.e. by defining a function which inverts suc, but that still requires boilerplate of one auxiliary function per constructor, and such functions are somewhat ugly to define because of the need to be total.
(Usual caveats re. missing something obvious apply.)
Ulf Norell's prelude for Agda contains a mechanism for automatically deriving decidable equality for a given datatype. The code is based on Agda's reflection mechanism and automatically generated extended lambdas for proving injectivity of constructors. I recommend taking a look at the code, even though it's not always as simple as it could be.