From the Idris 2 publication about linear types "Idris 2: Quantitative Type Theory in Practice":
For Idris 2, we make a concrete choice of semiring, where a multiplicity can be one of:
- 0: the variable is not used at run time
- 1: the variable is used exactly once at run time
- ω: no restrictions on the variable’s usage at run time
But for Haskell:
In the fashion of levity polymorphism, the proposal introduces a data type
Multiplicity
which is treated specially by the type checker, to represent the multiplicities:data Multiplicity = One -- represents 1 | Many -- represents ω
Why didn't they add a Zero?
In Idris, the value of a function argument can appear in the return type. You might write a function with type
This says "
vecLen
is a function that takes aNat
(call itn
) and aVect
of lengthn
and element typea
and returns aNat
(call itm
) such thatn = m
". The intent is to walk the linked listVect
and come up with its length as a runtimeNat
value. But the issue is thatvecLen
requires you to already have the length of the vector as a runtime value, because that's the veryn
argument we're talking about! I.e. it's possible to implement justYou can't not take
n
as an argument, because theVect
type needs its length as an argument to make sense. This is a somewhat serious problem, because having bothn
and aVect n a
duplicates information—without intervention the "classic" definition ofVect n a
itself is in fact space-quadratic inn
! So we need a way to take an argument that we know "in principle exists" but may not "actually exist" at runtime. That's what the zero multiplicity is for.This is the use of the zero multiplicity in Idris: it lets you talk about values that may not exist yet/anymore/ever inside of types so you can reason about them etc. (I believe in one talk Edwin Brady did, he used or at least noted you could use zero multiplicities to reason about the previous state of a mutable resource.)
But Haskell does not quite have this kind of dependent typing... so there just isn't a use case for zero multiplicities. From another point of view, the zero multiplicity form of
f :: a -> b
is justf :: forall (x :: a). b
, because Haskell is wholesale type-erased in a way that Idris and other dependently typed languages cannot easily be. (In this sense, IMO, I think Haskell has the whole dependent type erasure problem that other languages have such trouble with neatly solved—at the cost of having to use an awkward encoding for everything else about dependent types!)In the latter sense, the "dependent" Haskell (i.e. souped-up with
singletons
) way to take a dependent, unrestricted argument is this:and the "zero multiplicity" version is just