avh4 / elm-fifo

first in, first out (FIFO) queue

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Insert strategy

chikamichi opened this issue · comments

Hi,

I was looking for a FIFO implementation in Elm and just found yours. I have a question about the way insert is implemented. As I am fairly new to Elm, it may be a rather naive question, but still: let's learn :)

Currently, insert is:

insert : a -> Fifo a -> Fifo a
insert a (Fifo front back) =
    Fifo front (a :: back)

Because a Fifo starts as a pair of empty lists, adding a bunch of terms results in front being empty, and back holding the values. It explains why you needed to handle that "edge-case" in the remove operation:

-- pattern matching
Fifo [] back ->
  remove <| Fifo (List.reverse back) []

My question is this: wouldn't it be simpler to promote the first appended item to front upon insertion, so as to avoid the above pattern matching? Something like:

insert a (Fifo front back) =
    case fifo of
        Fifo [] [] ->
            Fifo [a] []
        Fifo front back ->
            Fifo front (a::back)

It would also require reworking remove so as to have front always be a 1-item list (or an empty list if the Fifo is eventually emptied).

I may be completely off tracks here, it's late at night :)

Note: such a refactoring would embrace the fact that the a FIFO queue's front is actually the oldest value, that is, a single node. Your implementation leverages two lists, and some clever tricks are required to sort/move those lists; it feels like it's not necessary.

So I guess my core, underlying question was actually whether it would be possible to define the Fifo type as being the combination of a single node (the front value) and a list (the back value). Turns out it's possible, I gave it a quick shot here: http://share-elm.com/sprout/56971b29e4b070fd20da88b5

What do you think?

I used an enumeration instead of a duo of lists, so the two core states of a FIFO are descriptive: it's either Empty, or it's not, in which case it's the combination of a Node (FIFO's front) and a List. I guess one could actually get rid of the Node and handle the FIFO with just a simple List, but semantically it sounds good.

I think the two lists are required to make it work in all cases.

It took me a little while, but I found this case that your implementation fails:

  empty
      |> insert 1
      |> insert 2
      |> insert 3
      |> remove |> snd  -- Removes 1
      |> remove |> fst   -- should remove 2
      |> assertEqual (Just 2)

It seems that only having one item in the head means that the order of the 2nd-oldest gets lost.

Ok, I reworked the implementation a little since I posted, so let me try with this case under the latest implementation.

All right, I was pretty sure about it already: I had fixed the problem in my PR #2.

See comments in #2

Closed via #2