The intuitive definition of NonEmptyList is:
type NonEmptyList<'t> = 't * 't list
But this cannot be passed to any function that expects a List<'t>. This is odd though, since intuitively, all non-empty lists are lists.
See Rich Hickey's "Maybe Not" talk
OOP solution is to use inheritance. Typical ML solution is to use type-classes.
F# sits in an awkward middle-ground where neither is a perfect fit.
I believe that dependently-typed languages solve this more elegantly.
There's also the syntactic inconvenience of wrapping at construction, where in theory the compiler could figure it out for you.
For example:
let xs = 1 :: 2 :: 3 :: []
Here xs is non-empty, but we must tell the compiler:
let xs = 1, 2 :: 3 :: []
TypeScript does a better job here (although a great cost!)
What you end up with is massive code duplication or lots of extra function calls:
xs
|> NonEmptyList.toList
|> List.map (fun x -> x + 1)
|> NonEmptyList.unsafeFromList
(I say this all as someone who really likes F#)
See Rich Hickey's "Maybe Not" talk
OOP solution is to use inheritance. Typical ML solution is to use type-classes.
F# sits in an awkward middle-ground where neither is a perfect fit.
I believe that dependently-typed languages solve this more elegantly.
There's also the syntactic inconvenience of wrapping at construction, where in theory the compiler could figure it out for you.
For example:
Here xs is non-empty, but we must tell the compiler: TypeScript does a better job here (although a great cost!)What you end up with is massive code duplication or lots of extra function calls:
(I say this all as someone who really likes F#)