Replace element recursive in list F# [duplicate] - recursion

This question already has answers here:
F# insert/remove item from list
(5 answers)
Closed 8 years ago.
I'm trying to the learn the basics of F# right now and was wondering how you could replace a element in a list recursively. So you would do something like this.

let replace index sub = List.mapi (fun i x -> if i = index then sub else x)
replace 0 'd' ['a';'b';'c']
> val it : char list = ['d'; 'b'; 'c']
This meets your criteria, with two minor changes to make it more conformant with F# style:
the index is zero-based
the list is the last argument, to support piping

A modification of the answer I linked to directly answer the question:
let rec insert v i l = //v - value to substitute, i - index at which to substitute, l - the list
match i, l with
| 0, x::xs -> v::xs //this line does the actual replace
| i, x::xs -> x::insert v (i - 1) xs //simply iterates one further through the list
| i, [] -> failwith "index out of range" // the given index is outside the bounds of the list
Note that this is not tail recursive and will Stackoverflow for large lists. Arrays or List would probably be a better choice if you need to do this type of operation.

Related

Map List onto shifted self

I have finally found an excellent entry point into functional programming with elm, and boy, do I like it, yet I still lack some probably fundamental elegance concerning a few concepts.
I often find myself writing code similar to the one below, which seems to be doing what it should, but if someone more experienced could suggest a more compact and direct approach, I am sure that could give some valuable insights into this so(u)rcery.
What I imagine this could boil down to, is something like the following
(<-> is a vector subtraction operator):
edgeDirections : List Vector -> List Vector
edgeDirections corners = List.map2 (\p v -> p <-> v) corners (shiftr 1 corners)
but I don't really have a satisfying approach to a method that would do a shiftr.
But the rules of stackoverflow demand it, here is what I tried. I wrote an ugly example of a possible usage for shiftr (I absolutely dislike the Debug.crash and I am not happy about the Maybe):
Given a list of vectors (the corner points of a polygon), calculate the directional vectors by calculating the difference of each corner-vector to its previous one, starting with the diff between the first and the last entry in the list.
[v1,v2,v3] -> [v1-v3,v2-v1,v3-v2]
Here goes:
edgeDir : Vector -> ( Maybe Vector, List Vector ) -> ( Maybe Vector, List Vector )
edgeDir p ( v, list ) =
case v of
Nothing ->
Debug.crash ("nono")
Just vector ->
( Just p, list ++ [ p <-> vector ] )
edgeDirections : List Vector -> List Vector
edgeDirections corners =
let
last =
List.head <| List.reverse corners
in
snd <| List.foldl edgeDir ( last, [] ) corners
main =
show <| edgeDirections [ Vector -1 0, Vector 0 1, Vector 1 0 ]
I appreciate any insight into how this result could be achieved in a more direct manner, maybe using existing language constructs I am not aware of yet, or any pointers on how to lessen the pain with Maybe. The latter may Just not be possible, but I am certain that the former will a) blow me away and b) make me scratch my head a couple times :)
Thank you, and many thanks for this felicitous language!
If Elm had built-in init and last functions, this could be cleaner.
You can get away from all those Maybes by doing some pattern matching. Here's my attempt using just pattern matching and an accumulator.
import List exposing (map2, append, reverse)
shiftr list =
let shiftr' acc rest =
case rest of
[] -> []
[x] -> x :: reverse acc
(x::xs) -> shiftr' (x::acc) xs
in shiftr' [] list
edgeDirections vectors =
map2 (<->) vectors <| shiftr vectors
Notice also the shortened writing of the mapping function of (<->), which is equivalent to (\p v -> p <-> v).
Suppose Elm did have an init and last function - let's just define those quickly here:
init list =
case list of
[] -> Nothing
[_] -> Just []
(x::xs) -> Maybe.map ((::) x) <| init xs
last list =
case list of
[] -> Nothing
[x] -> Just x
(_::xs) -> last xs
Then your shiftr function could be shortened to something like:
shiftr list =
case (init list, last list) of
(Just i, Just l) -> l :: i
_ -> list
Just after I "hung up", I came up with this, but I am sure this can still be greatly improved upon, if it's even correct (and it only works for n=1)
shiftr : List a -> List a
shiftr list =
let
rev =
List.reverse list
in
case List.head rev of
Nothing ->
list
Just t ->
[ t ] ++ (List.reverse <| List.drop 1 rev)
main =
show (shiftr [ 1, 2, 3, 4 ] |> shiftr)

how to get the Column of a matrix in Ocaml

I want to print out the column of a matrix but i keep getting an error.
Error: This expression has type 'a list but an expression was expected of type int
let rec get_column2 mat x = match mat with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else get_column2 t (x-1);;
let rec get_column mat x= match mat with
| [] -> raise (Failure "empty list")
| []::tv -> get_column tv x
| hv::tv -> get_column2 hv x::get_column tv x;;
Matrix example [[2;5;6];[3;5;3][3;6;8]]
The first part works fine on type int list so I added the second part to go through the int list list and cut them into int list's and then tryed to get the columns of each separately.
I also tryed it this way:
let rec get_column mat x =
let rec column matr y =
if matr = [] then raise (Failure "empty list") else
if y = 1 then List.hd matr else
column (List.tl matr) y-1;
in column (List.hd mat) x :: get_column (List.tl mat) x;;
The second example translates fine but then doesn't work. I get an Exception "tl". (I'm not sure the function nesting is done right since I'm just learning Ocaml).
get_column2 - your first function, works as it should. That is it will fetch the value of each row in the matrix. It's a good helper function for you to extract the value from a list.
Your second function get_column gets all the types right, and you're accumulating everything, except that instead of stopping when you have an empty list [] you end up throwing an exception. That is your matrix example will go through just nicely, until it has no more lists to go through, then it will always throw the exception. (because the recursion keeps going till it's an empty list, and Ocaml will do as you told it too, fail when it gets an empty list.
The only thing you were missing was the exception, instead of throwing an exception, just return an empty list. That way your recursion will go all the way and accumulate till it's an empty list, and at the final step where the matrix is empty, it will append the empty list to the result, and you're golden.
So your code should be:
let rec get_column2 mat x = match mat with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else get_column2 t (x-1)
let rec get_column mat x= match mat with
| [] -> [] (*doesn't throw an exception here*)
| []::tv -> get_column tv x
| hv::tv -> (get_column2 hv x)::get_column tv x
Instead of throwing the exception when it's an empty list, maybe you could check if the value of x is more than the length of the inner list.
Also, here's my implementation of doing it. It's still fairly basic as it doesn't use List.iter which everyone loves, but it doesn't rely on any additional packages. It makes use of nested functions so you don't expose them everywhere and pollute the namespace.
(*mat is a list of int list*)
let get_col mat x =
let rec helper rows x = (*helper function that gets the value at x*)
match rows with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else helper t (x-1)
in
let rec wrapper mat= (*function that walks through all the rows*)
match mat with
| [] -> []
| rows::tl -> (helper rows x)::(wrapper tl) (*keep accumulating value*)
in wrapper mat
How you can visualize the [] -> [] part is that when the recursion is at it's final stage (mat is reduced to an empty list), the wrapper function returns the empty list, which will be appended to the recursion stack (since we are accumulating the values in a list as per (helper rows x)::(wrapper tl)), and the recursion will complete.
You don't hit this error with your get_column2 as you tell ocaml to stop recursing and return a value when x=1.
Edit, Additional:
As Jeffrey mentioned, a much more elegant way of handling the error is adding the case for [row], where row is the last row in the matrix. You just return (helper row x) there. And you could have the empty matrix as a failure.
Example using your code:
let rec get_column mat x= match mat with
| [] -> raise (Failure "empty list") (*fail here, as we don't want to compute a matrix with no rows.*)
| [tv] -> get_column tv x (*just return the value*)
| hv::tv -> (get_column2 hv x)::get_column tv x
When I try your first example, I don't get a type error. When I run it, I get the "empty list" failure. So your description of your problem seems wrong.
If you want to treat an empty matrix as an error, you must be very careful to handle a 1 x n matrix as your base case. I don't see that in your code.

OCaml: Going from int list list to int

I am working on a OCaml motion detection program. It analyzes two images and detects if there was motion. One part requires me summing a row of values and then also summing an entire image. This is what I have currenly:
let rec sumImRow(maskedrow) =
match maskedrow with
| [] -> 0
| mskRhd::mskRtl -> mskRhd + (sumImRow mskRtl)
;;
let rec sumImage(maskedimage) =
match maskedimage with
| mskRhd::mskRtl -> (sumImRow mskRhd)::(sumImage mskRtl)
| _ -> []
;;
and the given value is int list list -> int list = <fun>.
I don't quite understand why this is giving me int list.
tl;dr: You construct a new list instead of summing the integers.
Well, we can agree that sumImRow has type int list -> int as it takes elements from the list and then return their sum.
sumImage will have a list argument as it deconstructs it in the pattern matching. It then returns the list of result of sumImRow, meaning sumImage gets as argument a list of what sumImRow takes and returns a list of results. So we indeed have int list list -> int list.
You can avoid that by replacing :: with + and [] with 0 in sumImage's matching result.
You can also make a more improved code by using List.fold_left:
let sumImRow l = List.fold_left (+) 0 l;;
let sumImage l = List.fold_left (List.fold_left (+)) 0 l;;
The two return values of sumImage are both lists. So naturally its return type is a list.
(Most likely you should be using + rather than :: in sumImage. And the base case should be 0 rather than [].)

Return index of an asked-for value of a list using fold in OCaml

I wrote a recursive version of index as follows
let index list value =
let rec counter num = function
| [] -> -1
| h::t ->
if h == value
then num
else (counter (num + 1)) t
in counter 0 list;;
It works, but then our professor said we should use a tail recursive version in order to not timeout on the server, so I wrote a new index function using fold, but I can't seem to figure out why if it doesn't find the element, it returns a number greater than the length of the list, even though I want it to return -1.
let index2 list value = fold (fun i v ->
if i > (length list) then -1
else if v == value then i
else i+1) 0 list;;
Here's my fold version as well:
let rec fold f a l = match l with
[] -> a
| (h::t) -> fold f (f a h) t;;
Your folded function is called once for each element of the list. So you'll never see a value of i that's greater than (length list - 1).
As a side comment, it's quite inefficient (quadratic complexity) to keep calculating the length of the list. It would be better to calculate it once at the beginning.
As another side comment, you almost never want to use the == operator. Use the = operator instead.
EDIT
Why do you redefine fold instead of using List.fold_left?
Your first version of index is already tail recursive, but you can improve its style by:
using option type instead of returning -1 if not found;
directly call index recursively instead of a count function;
use = (structural) comparator instead of == (physical);
use a guard in your pattern matching instead of an if statement.
So
let index list value =
let rec index' list value i = match list with
| [] -> None
| h :: _ when h = value -> Some i
| _ :: t -> index' t value (succ i)
in index' list value 0
And as already said, index2 does not work because you'll never reach an element whose index is greater than the length of the list, so you just have to replace i > (length list) with i = (length list) - 1 to make it work.
But index2 is less efficient than index because index stops as soon as the element is found whereas index2 always evaluate each element of the list and compare the list length to the counter each time.

Pattern matching in SML - representing a list as (x::y)

I just started learning functional programming and I find myself very confused by the concept of pattern matching (i'm using SML). Take for example the following expression to insert an element in an ordered list:
fun insert (n,nil) = [n]
| insert (n, L as x::l) =
if(n < x) then n::L
else x::(insert(n,l))
How can the list L be expressed as x::l? I know x refers to the first element of the list and l to the rest, but I don't know what to call this construct or how it can be used. I have read a lot but all the documentation I find doesn't mention this at all. Here is another example that doesn't use the 'as' keyword.
(*returns a list with the sum of each element added of two lists added together*)
fun addLists (nil,L) = L
| addLists (L,nil) = L
| addLists (x::xs,y::ys) =
(x + y)::(addLists(xs,ys))
Thank you for your help!
For the insert function here:
fun insert (n,nil) = [n]
| insert (n, L as x::l) =
if(n < x) then n::L
else x::(insert(n,l))
The | insert (n, L as x::l) part is a pattern which will be matched against. L as x::l is called an as pattern. It allows us to:
Pattern match against a non empty list, where x is the head of the list and l is the tail of the list
Refer to the entire matched list x::l with the name L
This is similar (although not totally the same) as doing:
| insert (n, x::l)
except that if you do that, the insert function will become:
fun insert (n,nil) = [n]
| insert (n, x::l) =
if(n < x) then n::x::l
else x::(insert(n,l))
So the big advantage of using the L as x::l as pattern over a non as pattern is that it allows us to refer to the entire list, not just its head and tail, and avoids an additional list construction when we need to refer to the entire list. Observe that the only difference in the 2 pieces of code is n::L and n::x::l. Since we use the as pattern L as x::l in the first insert function, we are able to do n::L instead of n::x::l. This avoids one :: operation (also known as cons operation).
As for this:
fun addLists (nil,L) = L
| addLists (L,nil) = L
| addLists (x::xs,y::ys) =
(x + y)::(addLists(xs,ys))
For the second pattern | addLists (x::xs,y::ys), in nowhere do we reconstruct the list x::xs and y::ys in the code following it, so we do not need as patterns. You could write it like:
fun addLists (nil,L) = L
| addLists (L,nil) = L
| addLists (ListX as x::xs, ListY as y::ys) =
(x + y)::(addLists(xs,ys))
and it'll still work, except that we do not refer to ListX or ListY here, and hence these two as patterns are unnecessary.

Resources