0

I am writing a function to remove neighbors from a list which have the same value. I don't understand what the syntax error is here. This is what I have:

let rec rem_dup_neighb l = 
let rec rem_dup_neighb_aux l lastseen retl = 
match l with 
 []->retl
|[()]->[()]
| (y::rest) -> if(y==lastseen) then rem_dup_neighb_aux l lastseen retl else rem_dup_neighb_aux l y (y::retl)
in rem_dup_neighb_aux l 9000 [];;

I get the following error for the last line of the function:

Error: This expression has type int but an expression was expected of type
     unit

As an example, if you pass in [1;2;2;3;5] to the function, it should return [1;2;3;5]

Any help is appreciated. Thanks

UPDATE: Function seems to be infinite looping:

let rec rem_dup_neighb l = 
let rec rem_dup_neighb_aux l lastseen retl = 
match l with []->retl
| (y::rest) -> if(y==lastseen) then rem_dup_neighb_aux l lastseen retl else rem_dup_neighb_aux l y (y::retl)
in
    match l with
    (lastseen::rest) ->  rem_dup_neighb_aux l lastseen []

UPDATE 2: wasn't reducing the problem per iteration. Function seems to be returning [5;3;2] instead of [1;2;3;5] now though.

let rec rem_dup_neighb l = 
let rec rem_dup_neighb_aux l lastseen retl = 
match l with []->retl
| (y::rest) -> if(y==lastseen) then rem_dup_neighb_aux rest lastseen retl else rem_dup_neighb_aux rest y (y::retl)
in
    match l with
    []->[]
    |(lastseen::rest) ->  rem_dup_neighb_aux l lastseen []

UPDATE 3:

let rec rem_dup_neighb l = 
let rec rem_dup_neighb_aux l lastseen retl = 
match l with []->retl
| (y::rest) -> if(y==lastseen) then rem_dup_neighb_aux rest lastseen retl else rem_dup_neighb_aux rest y (y::retl)
in
    match l with
    []->[]
    |(lastseen::rest) ->  rem_dup_neighb_aux l lastseen [lastseen]
10
  • Your updated function passes the same list to the recursive call of rem_dup_neighb_aux each time. You want the to proceed along the list with each recursive call, so pass rest there. Commented Feb 16, 2014 at 5:26
  • You're also missing the empty list case in the match at the bottom. Commented Feb 16, 2014 at 5:28
  • O right, thanks. Fixed the infinite loop. Hmm, the function is returning [5;3;2] instead of [1;2;3;5]. I see why the first element is getting removed. Also need to reverse the output somehow. Commented Feb 16, 2014 at 5:29
  • List.rev should suffice for that. (Accumulating a list and then reversing it at the end is quite a common pattern in functional programming.) Commented Feb 16, 2014 at 5:33
  • Not allowed to use library functions :/ Commented Feb 16, 2014 at 5:34

2 Answers 2

3

If one of the test cases has [()] as input, then you can't use 9000 as a fake value for the beginning of the list. You need to have a fake value of the same type as whatever is in the list. One idea would be to use the actual first value of the list.

As a side comment, it seems like you should just take out your second case in the match. By the second case, I mean the pattern that (after fixing up the code) matches a list of length one; i.e., the pattern [_]. With your approach (using a "last seen" value) there are only two cases, for empty and non-empty lists. Your special problems come at the beginning of the list (as you're experiencing now), not at the end.

Update

You can have a pattern match (a match expression) anywhere you like. So, you can have one after the in:

let rem_dup_neighbors aList =
    let rec aux l lastseen retl =
        ...
    in
    match aList with
    | pattern1 -> blah blah blah
    | pattern2 -> aux blah blah

Update 2

When calling yourself recursivelly, you have to pass a smaller problem. Your auxiliary function just keeps calling itself with the same list.

Sign up to request clarification or add additional context in comments.

8 Comments

by second case, you mean the else part of the if statement? Also, do you know how to access the first element of the list without using library functions?
See rewritten text. Use pattern matching to access list elements.
Hmm, I thought I would need that for the base case or the function would call itself infinitely.
Your base case is the empty list.
I thought that is what [_ ]->retl was. I replaced []->retl with [_ ]->retl. Are you saying leave []->retl and remove [_ ]->retl?
|
2

The match clause [()] -> [()] accepts and produces a unit list, which doesn't really make sense there. You probably should have written [_] -> retl, _ being the match syntax for "match anything".

5 Comments

Ok, what does the ",_" after retl mean on the right side of the arrow?
So I just removed the [()]->[()] line and changed []->retl to [_]->retl. However, one of the test cases for the function passes in [()] to the function so I get the error: Error: This expression has type unit but an expression was expected of type int .The error points to the test file
gsg is saying you should have [_] -> retl in your code. He then goes on to point out (after the comma) that _ is a pattern that matches any value. His punctuation is slightly confusing.
I see. Thanks for clearing that up. If possible could you address the new problem I have in my previous comment?
This function compares the list elements to 9000, which constrains things such that it can only accept lists of ints.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.