`a -> Void` get interpreted as "not a" or "from a follows contradiction" or equivalently "a is uninhabited". Combinatorially it's `0 ^ a` which for non-empty a is zero but is equal to 1 when a is empty (0^0=1). In other words there are no functions of type `a -> Void` for non-empty a and there's exactly one such function for uninhabited a (id :: Void -> Void).
`Void -> a` is interpreted "from falsehood, anything (follows)" https://en.wikipedia.org/wiki/Principle_of_explosion. Combinatorially a^0 = 1 for all a so there's exactly one such function. An easy way to define it is by induction on Void (which has no cases and you're done).
a^0 = 1
0^a = 0
0^0 = 1
The fact that there's precisely 1 function void -> a is considered rather special in category theory, and means that 'void' is the so called 'initial object' for the category (which is automatically unique up to isomorphism)."Void -> a" means that the function cannot be called, because there no way to conjure a Void value. In Haskell, you can do it by (ab)using 'undefined', but that's kind of cheating. However, if you're using Idris with totality checking, I don't think you'll actually get any code calling such a function compile.
The "a -> Void" means that the function can never return.
The “C” void is expressed by the unit singleton.
So it is |a|^1.
f :: Void -> a
f _ = let x = x in xAnd assuming the theory is consistent(so no infinite loops etc.) this is the only instance of that function, so the cardinality is 1.
Another way to look at it is as a constrained subset of the Cartesian product of domain and codomain. In this case the domain is the empty set, so the Cartesian product is empty too.
Take this Haskell code that passes the type checker:
bottom = bottom
f :: Int -> a
f _ = bottom
Here 'bottom' has the conceptual type Void/Bottom and checks successfully against the 'a'.So assuming we have this Void type in Haskell (I don't know if Haskell has it or not), this should also type check:
f :: Void -> a
f x = x
Just like bottom (of type Void) checked against the 'a' earlier, an argument of that type should also type check. {-# LANGUAGE RankNTypes #-}
type Bottom = forall a. a -- zero inhabitants
f :: Bottom -> a
f x = x
That passes the type checker just fine.I think you are running into some weird haskellisms with your Bottom-type.
The normal way of defining that in haskell is using the "EmptyDataDecls" pragma, like this:
{-# LANGUAGE EmptyDataDecls #-}
data Empty
g :: Empty -> a
g x = x
Which doesn't pass the type checker.(From a theoretic standpoint, I would have thought your Bottom was a essentially a type-level identity function..)
'forall a. a' is just how you define the bottom type in System F, which Haskell is somewhat based on. As a type it describes that a term of that type can just conjure a value of any type out of thin air, which is obviously nonsense. That what makes it the bottom type.
The sub typing behavior associated with that is just the normal subsumption rule of polymorphic functions. The same reason why you can pass a function of type 'forall a. a -> a' to something expecting a function of type 'Int -> Int'. The types don't 'match' directly, but they do under the subsumption rule.
With "forall a. a" I was coming from the persepctive of intuisionistic type theory where the usual parametric polymorphism just get subsumed by Π-types and universal quantification is usually represented with Π-types, so you would have:
forall a.a (Universal Quantification)
<==> Π(a : Type) a (Π-type)
<==> (a : Type) -> a (Agda-notation)
==> a -> a (Π-type as regular function type)
where Type represents any type. That's what I meant by "type-level identity function".