F# replace first element in list? - list

Hey, I'm trying to learn some f# basics and am stumbling along. I'm wondering how you would go about "replacing" the first element in a list.
Any help would be appreciated!

Here's a general purpose function. It will replace the head of a list with a new value if the list is non-empty, else it will return a single element list with the replace value.
let replaceHead newHead list =
match list with
| _ :: tail -> newHead :: tail
| [] -> [newHead]

You could 'cons' (using the ::-operator) the new first element to the tail (List.tail) of the original list:
let theList = [1; 2; 3; 4]
let firstReplaced = 0 :: (List.tail a)
Note that this will leave the original list (theList) untouched.

Related

Changin list which is an iput with function

Good morning,
I have a problem with coding using ocaml so I had to code a function that take on input list then add to this list an element.
But using this does'nt affect the list1 so how can I do this ?
Thank you.
let rec append list1 element list2 = match list2 with
[]-> list1
| e::l -> if ( element = e ) then e :: list1
else (append list1 element l)
;;
List are immutable in OCaml, you can't change this. You can write a function append that takes a list and returns a new list that appends an element to it.
For example, here is the prepend function that takes a list and an element and returns a new list with the given element prepended to the passed list,
let prepend xs x = x :: xs
The append function is a little bit trickier, since lists in OCaml are singly-linked, so it is easy to prepend but hard to append. To implement the append function you need an intermediate list, let's call it acc for accumulator. You then go through each element of the input list and add it to the accumulator. Since you're prepending, then once the input list is over your accumulator will have all the elements of the input list by in the reversed order, i.e., the first element (aka the head) of the acc list will be the last element of the input list. Now you what is left is to prepend the element that we want to append to the reversed acc list and reverse act. Here is the skeleton code for you
let append xs x =
let rec loop xs acc = match xs with
| ... -> ... in
loop xs []

Remove from list f#

I've been working this evening with lists in f# (creating, adding, searching etc) and have recently gotten stuck on a list item delete. The code is pretty straight forward.
let menu = [("pizza",17);("hotdog",5);("burger", 12);("drink",3);
("milkshake",4)]
//If key is in dictionary , return new dictionary with value removed
//otherwise return dictionary unchanged
let rec remove dict key =
match dict with
//if the list is empty, return an empty list
| [] -> []
//if the list is not empty and the head meets the removing criteria
//return a list obtained by reiterating the algorithm on the tail
//of the list
| (k,v) :: tl when k = key -> tl :: remove tl key
//if the list is not empty and the head does not meet the removing criteria
//return a list obtained by appending the head to a list obtained by
//reiterating algorithm on tail of the list
| (k,v) :: tl -> (k,v) :: remove tl key
The error comes from the final line of the function, | (k,v) :: tl -> (k,v) :: remove tl key. Apparently, it doesn't recognize (k,v) as the head of the list, and instead only sees a tuple with values. It makes sense, I don't know what else I would expect, but the problem is I don't know how to fix it. I tried putting the tuple inside of a list, like [(k,v)] but that made things even worse. I even tried | hd :: tl -> hd :: remove tl key but I had the exact same issue. Every other function I have written has accepted hd and tl as lists in my pattern matching.
How can I resolve this problem?
The second guard is wrong. You are using the tail twice, and since you are using it in a cons operation as first parameter it doesn't type check (it expects a single element, not a list).
Change it to:
| (k,v) :: tl when k = key -> remove tl key
I see one other mistake that you are making. It's a conceptual mistake rather than a bug in your code, but it will lead to more bugs unless you understand your mistake. You wrote:
Every other function I have written has accepted hd and tl as lists in my pattern matching.
(Emphasis mine). Your mistake is in thinking that when you write hd :: tl, both hd and tl are lists. You're half right: tl is indeed a list in that syntax, but hd is a single item. Proof:
let theList = [1; 2; 3; 4; 5]
printfn "The list: %A" theList
// Prints "The list: [1; 2; 3; 4; 5]"
match theList with
| [] -> printfn "The list was empty"
| hd :: tl -> printfn "Head was %A and tail was %A" hd tl
// Prints "Head was 1 and tail was [2; 3; 4; 5]"
When you use the syntax hd :: tl in pattern-matching, it splits the list into the first item (the head) and the rest of the list (the tail). When you use the syntax hd :: tl in a normal expression (e.g., everywhere that isn't a pattern match), you are taking a list called tl and a single item called hd, and prepending that item to the list, resulting in a brand-new list that has one more item at the front than the previous list did.
The sentence I quoted would have been correct if you had written:
Every other function I have written has accepted tl as a list and hd as a list item in my pattern matching.
I hope this helps you understand F# lists better!

Erlang change value of element in list

Hello is there a way to change the value of the head of a list in Erlang
Hd -> store2(Key, N,[New|List],New,false)
this is as close I came to changing it New is the new element to the Head element of the list
store(Key, N, TupleList, New) when is_integer(N), N > 0, is_tuple(New) ->
store2(Key, N, TupleList, New, false).
store2(_Key,_N,[], New, false) -> [New];
store2(Key, N,List, New, false) -> case fetch(Key, N, List) of
[] -> List;
false -> List++[New];
Hd -> store2(Key, N,[New|List],New,false)
end.
to clarify even further im using a function called fetch that I defined to find an element to replace with another element which is New
Just prepend your new head to the tail of List.
[New|tl(List)]
You usually write it as pattern matching
some_function(..., [_Old|Tail] = _List, ...)->
...
NewList = [New|Tail],
...

Pattern matching x::xs not splitting list accordingly in F#?

I'm new to F# and I'm trying to write a method split that splits a list into 2 pieces. It takes a tuple with the first element being the number of elements to split and the second element is the list . For example, split (2, [1;2;3;4;5;6]) should return ([1;2], [3;4;5;6]),
This is what I have so far, but for some reason it is returning the second element of the tuple as the original list without the head. I don't understand this because I thought that x::xs automatically makes x the head element and xs the rest of the list, which would mean that each recursive call is taking the tail of the previous list and chopping off the first term.
let rec split = function
|(n, []) -> ([], [])
|(0, xs) -> ([], xs)
|(n, x::xs) -> let temp = x :: fst (split(n-1, xs))
(temp, xs);;
The problem is on this line:
(temp,xs);;
here in your example, xs will always be [2;3;4;5;6] as long as n>0
You need to get the second element of the list with something like
|(n,x::xs) ->
let a,b = split (n-1,xs)
(x::a,b)

Error in code to flatten a list in Ocaml

Hello All I am trying to flatten a list in Ocaml. I am a newbie so please pardon me if my mistake is dumb
So for example, if input is [[1];[2;3];[4]] I should end up with [1;2;3;4].
The idea I am trying to use is as follows
Iterate through the list from the right (Using fold_right) with accumaltor = []
The pseudo code is as follows
func flatten(list, accumalator)
For each item from right to left in list
If Item is a scalar then n :: accumalator
Else fi Item is a list of form head :: tail then
head :: flatten (tail, accumalator).
I think that theoretically the algorithm is correct, but please let me know if you disagree.
Now to my OCaml code to implement this algorithm
let rec flatten acc x =
match x with
n -> n :: acc
| [x] -> x :: acc
| head :: remainder ->
head :: ( my_flat acc remainder )
and my_flat = List.fold_right flatten
;;
my_flat [] [[1];[2;3];[4]]
The Error I get is the following
Error: This expression has type 'a but an expression was expected of type
'a list
The error occurs on the line that reads head :: ( my_flat acc remainder ) in the last pattern in the match statement
Any help is appreciated.
In OCaml, all the elements of a list must be the same type. Thus the value [1; [2; 3]; 4] is invalid all by itself. It contains two elements that are of type int and one element of type int list. In essence, your statement of the problem to be solved is impossible.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
This sounds like a homework problem, so I'll just say that restricting yourself to lists that are valid in OCaml may make it easier to solve.
Edit
OK, the problem can now be solved!
The essence of the reported type error is something like this. You have your accumulated result acc (of type int list in the example). You want to add the list x (also of type int list) to it. You've broken x into head (an int) and remainder (an int list). As you can see, remainder is not a suitable argument for your my_flat function. It wants an int list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go to flatten and not to my_flat.
Another problem I see: the arguments of List.fold_right are: a function, a list, and a starting value. In your test call to my_flat, you're supplying the last two in the other order. The empty list [] is your starting value.
I hope this is enough to get you going. Since you're just starting out with OCaml there will probably be another problem or two before it works.
Edit 2
Here are a couple more comments, which might be spoilers if you're still working on your own solution....
A tidier version of your function my_flat is in the OCaml standard library under the name List.flatten. It's interesting to look at the implementation:
let rec flatten = function
[] -> []
| l::r -> l # flatten r
I'd call this a very elegant solution, but unfortunately it's not tail recursive. So it will consume some (linear) amount of stack space, and might even crash for a very long list.
Here's one based on the same idea, using the standard FP accumulator trick to get tail recursive behavior (as noted by Thomas):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.
You can start by writing directly your algorithm, by decomposing the base cases of your input value, ie. the input list is either empty, or the head of the input list is empty, or the head of the input list has a head and a tail:
let rec flatten = function
| [] -> []
| [] :: t -> flatten t
| (x::y) :: t -> x :: (flatten (y::t))
You can then optimize the function, because this code is not tail-recursive and thus will crash when lists become too big. So you can rewrite this by using the usual technique:
let flatten list =
let rec aux accu = function
| [] -> accu
| [] :: t -> aux accu t
| (x::y) :: t -> aux (x::accu) (y::t) in
List.rev (aux [] list)
So my advice is: start by decomposing your problem based on the input types, and then later use accumulators to optimize your code.
I like this one, where the auxiliary function takes the accumulator, the first element of the list of lists, and the rest of the list of lists, it is clearer for me :
let flatten list =
let rec aux acc list1 list2 =
match list1 with
| x :: tail -> aux (x :: acc) tail list2
| [] ->
match list2 with
| [] -> List.rev acc
| x :: tail -> aux acc x tail
in
aux [] [] list
Thanks for all your help
Here is the code I used to solve this problem
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> head :: ( flatten_each acc remainder )
in
List.fold_right flatten_each ( List.rev list ) []
;;
Edit: as pointed out by Thomas this solution is not tail recursive. Tail recursive version is below
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> (flatten_each (acc # [head]) remainder )
in
List.fold_right flatten_each list []
;;