Enforcing a length on a collection

Is there any way to use the type system to set a minimum length on a collection?

For example: a list with two or more objects. I could easily do the following:

type alias Data =
    List Int

fromList : List Int -> Maybe Data
fromList list =
    case list of
        xa :: xb  ->
            Just <| list
        _ ->
            Nothing

And then not allow Data to be generated in any other way.

But having a List still implies the [] and [1] case, which could ultimately lead to confusion. So is there a smarter way to build a collection like this?

1 Like

What about this type?

type TwoOrMore a = TwoOrMore a a (List a)
4 Likes

Yes, it is possible, and what @unsoundscapes suggests is indeed what is used in practice. As an example see List.NonEmpty.

The main caveat is that when introducing such a type, you’ll have to write all the convenience functions you know and love from ‘normal’ lists for this new data-structure. Because Elm has no dependently-typed features whatsoever, there is no way to automate this boilerplate for you :man_shrugging:.

2 Likes

I’d probably go for either @unsoundscapes solution or this:

type alias TwoOrMore value = (value, value, List value)

numbers : TwoOrMore Int
numbers = ( 0, 1, [ 2, 3 ] )
3 Likes

Thanks everyone. These are all great answers!

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.