# No duplicates challenge in Elm

### Anton github logo May 8・1 min read

There is a 99 Elm problems book (originally was for Prolog).

Write a function to remove consecutive duplicates of list elements.

``````noDupes [1, 1, 2, 2, 3, 3, 3, 4, 5, 4, 4, 4, 4]
== [1, 2, 3, 4, 5, 4]
``````

I'm doing something wrong here. Am I on the track or completely off track?

``````noDupes : List a -> List a
noDupes list =
case list of
[] -> []
x::y::xs ->
if x == y then
x :: noDupes xs
else
x::y::xs
x::xs ->
if x == xs then
x :: xs
else
x
``````

The compiler already gave me a heads up that I'm comparing an element to a list:

``````17|             if x == xs then
^^^^^^^
The left side of (==) is:

a

But the right side is:

List a

Different types can never be equal though! Which side is messed up?

Hint: Did you forget to add [] around it?
``````

Interesting I just wrapped the x in [x]. But I now have the second the last case to deal with.

DISCUSS (11) Sore eyes?

dev.to now has dark mode.

Go to the "misc" section of your settings and select night theme. You're forgetting to handle the case of a list with a single element.

Also, in the case `x :: y :: xs`, when `x` is not equal to `y` you should return `x :: (noDupes y :: xs)` to make sure the rest of the list gets deduplicated.

I don't think you need to handle the case `x :: xs` at all, but you might need to handle the case of a list with two elements.

How do I pattern match on the list with two elements?

``````noDupes : List a -> List a
noDupes list =
case list of
[] -> []
x::y ->
if x == y then
x :: list
else
x :: y :: list
x::y::xs ->
if x == y then
x :: noDupes xs
else
x :: (noDupes y::xs)
``````

And in the case of two element how do you add that to the rest of the list? As you can see I use "list" in the second case. I don't think it's correct.

Now I have some missing possibilities:

``````This `case` does not have branches for all possibilities:

9|>    case list of
10|>        [] -> []
11|>        x::y::[]->
12|>            if x == y then
13|>                x :: list
14|>            else
15|>                x :: y :: list
16|>        x::y::xs ->
17|>            if x == y then
18|>                x :: noDupes xs
19|>            else
20|>                x :: (noDupes (y::xs))

Missing possibilities include:

[_]

I would have to crash if I saw one of those. Add branches for them!

Hint: If you want to write the code for each branch later, use `Debug.todo` as a
placeholder. Read <https://elm-lang.org/0.19.0/missing-patterns> for more
guidance on this workflow.

``````

You cases check for 1) an empty list, 2) a list with exactly two elements, and 3) a list with 2 elements and a tail. You forgot to check for the singleton list (a list with exactly one element) which is what the compiler is warning you about. Note, checking for a list with exactly two elements is not effective for this particular program.

I'm taking a note of "checking for a list with exactly two elements is not effective for this particular program."

Interesting this code

``````noDupes : List a -> List a
noDupes list =
case list of
[] -> []

[x] -> [x]

x::y::xs ->
if x == y then
x :: noDupes xs
else
[x]

``````

when applied to

``````noDupes [ 2, 2, 2, 1, 1, 1 ]

``````

returns

``````[2, 2]
``````

the `x::y::xs ->` case does not recur in the `else` branch, so an input of `[1,2,2,2,3,3,3]` will simply return `` when the first two elements of the input do not match - leaving the `[2,2,2,3,3,3]` portion completely unprocessed.

Consider this implementation

``````noDupes : List a -> List a
noDupes list =
case list of
[] ->
[]

[ a ] ->
[ a ]

a :: b :: more ->
if a == b then
noDupes (a :: more)
else
a :: noDupes (b :: more)
``````

When we test it

``````noDupes [1, 1, 2, 2, 3, 3, 3, 4, 5, 4, 4, 4, 4]
-- [ 1, 2, 3, 4, 5, 4 ] : List number

noDupes ["a", "b", "b", "c", "c", "c", "d", "d", "c" ]
-- [ "a", "b", "c", "d", "c" ] : List String
``````

I had this noDupes (a :: more) in the else branch when experimented with the code but didn't consider putting that in the first branch.

Thank you. I appreciate your help.

Haha,I like to think I know FP well, but, when I try to do recursive functions like this, my whole brain freezes up 😅

It's all about mastering inductive reasoning.

``````someFunc n =
if n == 0 then
-- do something when n IS zero (base case)
else
-- do something where n is (by inductive reasoning) NOT zero
``````

Or

``````someFunc list =
if List.isEmpty list then
-- handle the empty list (base case)
else
-- the list (by inductive reasoning) has at least one element
``````

Pattern matching streamlines this for us by allowing us to express the base case and any induction steps using a nice syntax

``````someFunc n =
case n of
0 ->  -- base case
_ -> -- induction step
``````

Or

``````someFunc list =
case list of
[] -> -- base case
first :: more -> -- induction step
``````
Classic DEV Post from Nov 21 '18

## Vanilla JS, back to basics - Part. 2: hoisting  