How does Fin actually work?
data Nat = Z | S Nat
data Fin : (n : Nat) -> Type where
FZ : Fin (S k)
FS : Fin k -> Fin (S k)
- Where does
kcome from? - Why isn't
FZalways the value of(n: Nat)+ 1? - How does
Fin"know" not to exceed its type bound?
This mailing list talks about implicits, but I'm lost as to how and where these values come from.
Given this basic example:
t1 : Fin 3
t1 = FZ
What is t1's value? t1's type is Fin 3, but FZ experimentally (appears) to represent zero. Which is why we can "count" with it just like we do with Nat:
t2 : Fin 3
t3 = FS (FS FZ) -- this is equal to 2?
But this confuses me given the constructor!
FZ : Fin (S k)
If we're saying that t1 has type Fin 3, does that mean that k takes on the value of the n in the type? If that were the case, and FZ calls S on that Nat, then why isn't FZ representing 4?
This is obviously not the case.
So I'm completely and absolutely lost on how FZ acts like 0, and where k comes from, and how the compiler knows when k has become >= n just based on this data type.
I think what's confusing you is that you're thinking
kis the value of theFin n. It's not. It's just book-keeping to make sure theFin nis always less thann.Where does k come from?
In
kis an (erased) implicit argument. It's shorthand forso it's passed implicitly, but it's still an argument to
FZ. In most cases, it can be unambiguously inferred from the context. The compiler will tell you if it can't.Why isn't
FZalways the value of(n: Nat) + 1?FZalways represents zero*. Thisis the same as
It's a zero that's less than three. These are also all zero
How does Fin "know" not to exceed its type bound?
Since
FZis always zero, andFS FZis always one, and so on, it's impossible to express aFin nwith value greater than or equal ton. Let's try to create aFin 2of value two.To see why this won't compile, fill in the implicits (note that
FSalso has an implicit argument calledk):We're creating a
Fin 2so the outer-mostFSmust haveS k = 2sok = 1. Each successiveFSwe go down we reducekby one (see the argument toFSisFin kto produce aFin (S k)- so one less). Eventually we reachFZbut by this point there's isn't aNatto represent this value ofk. The compiler balks with such a statementYou can do the same for a
Fin 2of value three etc. Have a try.Other qus
Given
What is
t1's value? It'sFZ, andFZrepresents zero.Yes, it's two.
If we're saying that
t1has typeFin 3, does that mean thatktakes on the value of thenin the type? If that were the case, andFZcallsSon thatNat, then why isn'tFZrepresenting 4?S ktakes on the value ofn.*this is actually a matter convention, but I'll avoid confusing things by going into that