Exactly, if you're doing filtering and reducing then you will be not be able to maintain the type-level guarantee that the resulting collection is still non-empty, so you're going to need to be making the moral equivalent of that runtime test all over again anyway. If you want to make it more concise then you could wrap it up in a firstAndLast: (Element, Element)?
convenience property. A NonEmpty
collection type can only carry its weight if you're using a collection in an immutable, append-only or reorder-only fashion across a large enough call graph.
I think you can also delete elements, but you have the constraint not to delete anything if only one element is available :).
"wrap it up in a firstAndLast: (Element, Element)?
convenience property" β this doesn't help in reality. Mental model is that it is not optional, but compiler still can not prove that.
As for filter-map & map-reduce, sorry for misleading. Travelroute itself is not filtered, it is only mapped. Saying filter-map & map-reduce is supposed in more wide meaning, not just applying functions like travelRoute.filter {}.map {}.
Examples I have provided are battle tested on real application from travel domain. Convenience of using NonEmptyArray is not theoretical reasoning. It is proven by real code and help a lot to reduce amount of code.
I just only share my own experience. If it was easy to write this code using Array and current language abilities, trust me, we would do) But using of plain Array leads to lots of meaningless if-let constructions or unsafe index operations. NonEmptyArray solves all these problems. The question is "Why should we suffer from using plain Array and write more complicated code, if there is alternative solution?"
Although, other variants are possible. If we have fixed size collections, like Array<Int, 1...>
, then NonEmptyArray is not needed by itself. We can simply make typealias NonEmptyArray<T> = Array<T, 1...>
Unfortunately, map
et consortes will always map to a plain Array
. You canβt map a Set
to a new Set
, for instance.
Unless Swift would introduce higher kinded types, this is correct.
This will be fixed in future