"Collections" and phantom types

For a Todo List App, I have come up with a custom data type for collections of tasks. Because I want to edit specific tasks inside a collection, each task gets an ID.

However, the IDs are only unique inside a collection, so I need to keep track of where the task came from. For this I’m using phantom types.

-- Tag for the "done" collection
type Done = Done

-- Empty collection for "done" tasks
tasks = empty Done

updatedTasks = addTask "Buy milk" tasks

Now imagine I render the tasks in the list by mapping the collection (which was converted toList) to Html Msg. I then can add a message for editing each item using its ID.

renderSingleTask task =
    div [] [ text (getAction task)
        , button [onClick <| getId task] [ text "Edit" ]
        ]

Right now, I am only allowing editing of one list, so my message type looks like this:

Edit (TaskId Done) String

This means that it only accepts IDs from the Done list. Everything else throws a compiler error. I keep track of the currently edited item in my model using a field editing : Maybe (TaskId Done, String).

Now I want to allow edits to all lists. But since I need to keep track of which item I’m currently editing, this entails also keeping track of the list the item is coming from (one can consider this as being part of its ID). So having two lists, one for current, the other for done tasks, I have two types:

type Current = Current
type Done = Done

But I see no way of specifying the editing field in my model to allow either one. I would like something like:

editing : Maybe (TaskId (Current | Done), String)

Of course that’s a syntactical error. I’ve read a bit about Haskell and I think this is a use case for kinds. But I’m not entirely certain and kinds don’t exist in Elm (as they shouldn’t). This leaves me wondering how to work around the issue.

I am beginning to think that I modeled the collections wrong. So if you know how to solve the issue, even if it means modifying the way my collections work, then please tell me! :slight_smile:

Probably the easiest is to declare a new custom type?

type EditableTask
    = CurrentTask (TaskId Current)
    | DoneTask (TaskId Done)

I have not yet made it work, but I feel this is the right solution. It wraps the TaskId with additional information on which Collection it belongs to, which is what I need.

I don’t know why I didn’t see that solution myself. So thank you for pointing it out! :slight_smile:

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