Note that NonEmpty a is really just a tuple of an a and an ordinary, possibly-empty [a]. This conveniently models a non-empty list by storing the first element of the list separately from the list’s tail: even if the [a] component is [], the a component must always be present.
Wat? How can I “store the first element of the list separated from the lists tail” when the list is empty? Whether a list is empty or not is a runtime possibility, not a compile-time possibility.
Someone care to explain this part? It does not compute at all for me.
During the parsing step, you check that the list has at least one element. If it does not, you report an error to the user and exit. If it does, you take the first element in the least and store it in the left side of your tuple, and then the remaining elements of the input list go into the right side of your tuple.
So, for example: [1, 2, 3] → (1, [2, 3])
Or also: [1] → (1, [])
If the user gives you [], then you cannot represent that with your tuple, you necessarily have to error.
A list can store zero or more elements. A NonEmpty can store one or more element. That’s all.
This overall strategy – representing the top of a list as a dedicated value – shows up elsewhere, notably in Forths, where it is called “top of stack” and often stored in a dedicated CPU register.
So it’s the implementation that has to ensure a NonEmpty is returned, but that’s up to the developer, correct? The developer still holds the gun to shoot themselves in the foot by returning an empty list, IINM.
If the return type of a function is NonEmpty the value returned is guaranteed to be non-empty because it is not possible to construct an empty NonEmpty value. That’s the “make illegal states unrepresentable” mantra in action.
At runtime you might get a list from an API response or something, and it might be empty. At that point you have a regular list. Following the advice from the article you want to parse that data to transform it into the types representing your legal states. So if the list is not supposed to be empty then somewhere you have a function that takes the possibly-empty list, and returns a value of type NonEmpty. But if the list actually is empty that function will fail so it has to be able to return or throw an error. The article uses the Maybe type for that which is one of the Haskell types for functions that can fail.
Once you have parsed the input list, and successfully gotten a NonEmpty value the rest of your code can safely access the first element of the list because a value of that type is guaranteed to have at least one value.
Wat? How can I “store the first element of the list separated from the lists tail” when the list is empty? Whether a list is empty or not is a runtime possibility, not a compile-time possibility.
Someone care to explain this part? It does not compute at all for me.
Anti Commercial-AI license
During the parsing step, you check that the list has at least one element. If it does not, you report an error to the user and exit. If it does, you take the first element in the least and store it in the left side of your tuple, and then the remaining elements of the input list go into the right side of your tuple.
So, for example:
[1, 2, 3] → (1, [2, 3])
Or also:
[1] → (1, [])
If the user gives you
[]
, then you cannot represent that with your tuple, you necessarily have to error.A list can store zero or more elements. A
NonEmpty
can store one or more element. That’s all.This overall strategy – representing the top of a list as a dedicated value – shows up elsewhere, notably in Forths, where it is called “top of stack” and often stored in a dedicated CPU register.
You cannot, and that’s why that type declaration models a
NonEmpty
that a type checker can enforceSo it’s the implementation that has to ensure a
NonEmpty
is returned, but that’s up to the developer, correct? The developer still holds the gun to shoot themselves in the foot by returning an empty list, IINM.Anti Commercial-AI license
If the return type of a function is
NonEmpty
the value returned is guaranteed to be non-empty because it is not possible to construct an emptyNonEmpty
value. That’s the “make illegal states unrepresentable” mantra in action.At runtime you might get a list from an API response or something, and it might be empty. At that point you have a regular list. Following the advice from the article you want to parse that data to transform it into the types representing your legal states. So if the list is not supposed to be empty then somewhere you have a function that takes the possibly-empty list, and returns a value of type
NonEmpty
. But if the list actually is empty that function will fail so it has to be able to return or throw an error. The article uses theMaybe
type for that which is one of the Haskell types for functions that can fail.Once you have parsed the input list, and successfully gotten a
NonEmpty
value the rest of your code can safely access the first element of the list because a value of that type is guaranteed to have at least one value.