Well into this year and I have very little interesting things to write about, I'm afraid. Just pasting a blurb here that shouldn't blow any minds, but speaks to how cute and easy things can be.
At work we needed to keep track of the user's n most recent searches and show them in a dropdown menu. They're first-in, first-out, but if a user selects a previous search and re-runs it, it jumps back up to the top of the history. There's no need to remove anything from the list; a history item can only be pushed out by new searches. O(n) is okay because n is small. With such convenient constraints, it was simple enough to just do this.
{-# LANGUAGE UnicodeSyntax #-}
data Queue a = Queue { limit ∷ Int, values ∷ [a] } deriving Show
enqueue ∷ Eq a ⇒ a → Queue a → Queue a
enqueue α (Queue l ω) = Queue l $ take l $ (α :) $ filter (/= α) ω
A three item queue.
q = Queue 3 []
Queue {limit = 3, values = []}
Adding two items.
enqueue 2 $ enqueue 1 $ q
Queue {limit = 3, values = [2,1]}
Bumping the first item back to the top.
enqueue 1 $ enqueue 2 $ enqueue 1 $ q
Queue {limit = 3, values = [1,2]}
Pushing old items past the limit of 3.
enqueue 4 $ enqueue 3 $ enqueue 1 $ enqueue 2 $ enqueue 1 $ q
Queue {limit = 3, values = [4,3,1]}
That's it. take
and filter
probably won't result in two traversals due to laziness, though it hardly matters. I like how optimistic this wound up being.