How can finite numbers work? (dependent types)

纵饮孤独 提交于 2019-12-01 18:14:05

Think about the index as an upper bound for any number that can be represented by Fin n. For example, Fin 4 contains all natural numbers less than 4. Here's a data declaration:

data Fin : ℕ → Set where

How does the definition relate to this? The definition of natural numbers has two parts: zero and suc; for Fin, we'll call those fzero and fsuc.

With our upper bound interpretation, fzero can be given any upper bound as long as it is not zero (0 ≮ 0). How do we represent that the bound can be anything other than zero? We can force that simply by applying suc:

fzero : {k : ℕ} → Fin (suc k)

This gives us precisely what we need: no-one can write fzero in such a way that its type is Fin 0.

Now the fsuc case: we have a number with some upper bound k and we want to create a successor. What can we tell about the upper bound? It surely increases by at least one:

fsuc : {k : ℕ} → Fin k → Fin (suc k)

As an exercise, convince yourself that all numbers less than n can be represented by Fin n (in only one possible way).


How does the type checker accept one and reject another? In this case it's simple unification. Let's take a look at this code:

test : Fin (suc (suc zero))
test = ?

When we write fsuc, Agda has to figure out the value of k. To do that, it takes a look at fsuc constructor: it constructs a value of type Fin (suc k) and we need suc k = suc (suc zero); by unifying these two, we get that k = suc zero. So next:

test = fsuc ?

Now, the expression following fsuc (represented by ?, a hole) has a type Fin (suc zero) (since k = suc zero). When we fill in fzero, Agda tries to unify suc zero with suc k₂, which of course succeeds with the solution k₂ = zero.

If we decide to throw in another fsuc:

test = fsuc (fsuc ?)

Then using the same unification as above, we get that the type of the hole must be Fin zero. So far this type checks just fine. However, when you try to stuff fzero in there, Agda has to unify zero with suc k₃ - no matter the value of k₃, suc of something can never be zero, so that fails and you get a type error.


Another representation of finite numbers (that is arguably less plesant to work with) is a pair of natural number and a proof that it is less than the bound.

open import Data.Product

Fin' : ℕ → Set
Fin' n = Σ ℕ (λ k → k < n)

The original Fin can be thought as a version of Fin' where the proof is baked directly into the constructors.

The short answer is that the FiniteNum Zero type is empty, because both constructors return FiniteNum indexed with a non-zero natural number. Now try to answer the following: how many elements does FiniteNum (Succ Zero) have? How do they look like? Repeat for 2,3,4...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!