Model a Set with at least one element

Hi everybody,

That’s may first post in the Elm community!

I’m struggling on the best way to model a Set with at least one element inside.
The idea is to have a Stored type this a No / Yes Set StorageMedium

Someone can point me towards the goal?
Thank you,
Paolo

I might have used one of the following personally. I don’t know if that’s what you wanted

module StrictSet exposing (init, empty, toSet, insert, remove, fromSet)
import Set exposing (Set)

type StrictSet comparabble
    = Empty
    | Present (Set comparabble)

init : comparable -> StrictSet comparable
init =
    Present

empty : StrictSet comparable
empty =
    Empty

toSet : StrictSet comparabble -> Set comparabble
toSet set =
    case set of
        Present a ->
            a

        _ ->
            Set.empty

insert : comparable -> StrictSet comparable -> StrictSet comparable
insert item set =
    Present <| Set.insert item (toSet set)


remove : comparable -> StrictSet comparable -> StrictSet comparable
remove item set =
    let
        currentSet =
            Set.remove item <| toSet set
    in
    set
        |> Set.remove item
        |> fromSet

fromSet : Set comparable -> StrictSet comparable
fromSet set =
    if Set.isEmpty set then
        Empty

    else
        Present set

map : (comparable -> b) -> StrictSet comparable -> StrictSet comparable
map function set =
    case set of
        Present s ->
            Present <| function s

        Empty ->
            Empty

I would also make sure to hide the StrictSet constructor so other packages cannot call directly Present and Empty

I guess you can model it something like this:?

type alias NotEmptySet a =
  ( a, Set a)

And you can expose fuctions to convert it to and from a normal set:

NotEmptySet.singleton item =
  ( item, Set.empty )

NotEmptySet.toSet (firstOfSet,restSet) =
  Set.insert firstOfSet restOfSet

NotEmptySet.insert item (firstOfSet,restSet) =
  if item == firstOfSet then
    (firstOfSet,restOfSet)
  else
    (firstOfSet, Set.insert item restOfSet)
2 Likes

I’d just make a module mirroring the set functions using

module NonemptySet exposing (NonemptySet, ...)

type NonemptySet a = NonemptySet (Set a)

and then implement the logic for each case (what happens when you try to remove the last remaining element etc).

Others have already given good answers. I was thinking it might also be worthwhile looking at some of the other “non-empty” packages. Searching the package site for “non empty” gives 3 results for List, one for String and one for Array. If you have a look at their APIs and source code it could provide some more detailed inspiration! Particularly any differences they have from the core packages.

Thank you to everyone for the great suggestions!

I’m still learning, but I’m enjoying Elm power in modelling properly the data!
Coming from procedural languages with less expressive power, that’s delightful …

Use this package.

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