I came across this function : List.map. What I have understood is that List.map takes a function and a list as an argument and transforms each element in the list.
List.iter does something similar (maybe?), For reference see the example below.:
# let f elem =
Printf.printf "I'm looking at element %d now\n" elem in
List.iter f my_list;;
I'm looking at element 1 now
I'm looking at element 2 now
I'm looking at element 3 now
I'm looking at element 4 now
I'm looking at element 5 now
I'm looking at element 6 now
I'm looking at element 7 now
I'm looking at element 8 now
I'm looking at element 9 now
I'm looking at element 10 now
- : unit = ()
Can someone explain the difference between List.map and List.iter?
NOTE: I am new to OCaml and functional programming.
List.map returns a new list formed from the results of calling the supplied function. List.iter just returns (), which is a specifically uninteresting value. I.e., List.iter is for when you just want to call a function that doesn't return anything interesting. In your example, Printf.printf in fact doesn't return an interesting value (it returns ()).
Try the following:
List.map (fun x -> x + 1) [3; 5; 7; 9]
Jeffrey already answered this question fairly thoroughly, but I would like to elaborate on it.
List.map takes a list of one type and puts each of its values through a function one at a time, and populates another list with those results, so running List.map (string_of_int) [1;2;3] is equivalent to the following:
[string_of_int 1; string_of_int 2; string_of_int 3]
List.iter, on the other hand, should be used when you only want the side effects of a function (e.g. let s = ref 0 in List.iter (fun x -> s := !s + x) [1;2;3], or the example you gave in your code).
In summary, use List.map when you'd like to see something done to each element in a list, use List.iter when you'd like to see something done with each element in a list.
Related
I am new to F# and am having trouble with my code. Its a simple problem to define a function, search, with that take a boolean function and a list and return an index. So for example:
> search (fun x -> x > 10) [ 2; 12; 3; 23; 62; 8; 2 ];;
val it : int = 1
> search (fun s -> s < "horse") [ "pig"; "lion"; "horse"; "cow"; "turkey" ];;
val it : int = 3
What I have as of right now finds the right match but what I cant figure out is how to return a number instead of the rest of the list. I know I'm getting the list instead of a value back because I wrote "if f head then list". What I don't know is what I should put there instead or if what I have is not going to get the result I want.
Below is the code I have written.
let rec search f list =
match list with
| [] -> [-1]
| head::tail ->
if f head then list
else search f tail
Returning a number is easy, you just... return it. Your problem is that you don't have a number to return, because you can't derive it directly from the current state. You have to keep track of the number yourself, using some internal state variable.
When using recursion you change state by calling your function recursively with "modified" arguments. You're already doing that with the list here. To keep internal state in a recursive function you have to introduce another argument, but not expose it outside. You can solve that by using an internal recursive helper function. Here's one that keeps track of the previous item and returns that when it encounters a match:
let search f list =
let rec loop list prev =
match list with
| [] -> None
| head::tail ->
if f head then prev
else loop tail (Some head)
in
loop list None
That's a silly example, but I don't want to just solve your homework for you, because then you wouldn't learn anything. Using this you should be able to figure out how to keep a counter of which position the current item is in, and return that when it matches. Good luck!
You typically define an inner recursive function to help you carry state as you loop, and then call the inner function with an initial state.
let search predicate list =
let rec loop list index =
match list with
| [] -> -1
| head::tail ->
if predicate head then index
else loop tail (index + 1)
loop list 0
I'm currently interested in F# as it is different to everything I have used before. I need to access the first element of each list contained within a large list.
If I assume that the main list contains 'x' amount of lists that themselves contain 5 elements, what would be the easiest way to access each of the first elements.
let listOfLists = [ [1;2;3;4;5]; [6;7;8;9;10]; [11;12;13;14;15] ]
My desired output would be a new list containing [1;6;11]
Currently I have
let rec firstElements list =
match list with
| list[head::tail] ->
match head with
| [head::tail] -> 1st # head then firstElements tail
To then expand on that, how would I then get all of the second elements? Would it be best to create new lists without the first elements (by removing them using a similar function) and then reusing this same function?
You can use map to extract the head element of each child list:
let firstElements li =
match li with [] -> None | h::_ -> Some h
let myfirstElements = List.map firstElements listOfLists
I'm using Ocaml's speak with little lookup on F# so this may be inaccurate, but the idea applies.
EDIT: You can also use List.head which makes it more concise and will return a int list instead of int option list. However, it throws an exception if you hits an empty list. Most of the time, I'd avoid using List.head or List.tail in this case.
The easisest way to access the first element in a list is List.head. As you have a list of lists, you just need to List.map this function:
let listOfLists = [ [1;2;3;4;5]; [6;7;8;9;10]; [11;12;13;14;15] ]
listOfLists
|> List.map List.head
//val it : int list = [1; 6; 11]
Now if you need to access other elements, you can use List.item or just index into your list with xs.[1]. But please keep in mind, that for large lists this will be inefficient and if you want fast look up use an array.
listOfLists
|> List.map (List.item 1)
//val it : int list = [2; 7; 12]
With indexing:
listOfLists
|> List.map (fun x -> x.[1])
This is my function
let rec helper inputList = function
| [] -> []
| a :: b :: hd ->
if a = b then helper ([b::hd])
else a :: helper (b::hd)
It's not complete, however I can't see why I keep getting the error in the title at helper ([b::hd]). I've tried helper (b::hd) or helper (b::hd::[]) however all come up with errors. How do I make it so that it works?
When you use function you are supplying a pattern for the parameter of the function. But you already have a parameter named inputList. So this function helper is expecting two parameters (but it ignores the first).
You can fix this by removing inputList.
You also have a problem in your first recursive call to helper. Your expression [b :: hd] is a list of lists. I suspect that you want something more like just b :: hd here.
There is at least one other problem, but I hope this helps get you started.
There are multiple errors here. One is that the keyword function means we have an implicit parameter over which we are working. So the pattern matching happens on that "invisible" parameter. But here you defined probably the explicit one: inputList. So we can remove that one:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper ([b::hd]) else a :: helper (b:: hd)
Next there is a problem with the types: in the recursion, you use:
helper ([b::hd]); and
a :: helper (b:: hd)
But you put these on the same line, and that makes no sense, since the first one passes a list of lists of elements, and the second a list of elements. So the result of the first one would be a list of list of elements, and the second one a list of elements. It does not make sense to merge these.
If I understood correctly that you want to ensure that no two consecutive elements should occur that are equal, then we should rewrite it to:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)
You have defined two patterns here:
one for the empty list; and
one for a list with at least two elements.
The second one will perform recursion on the tail of the list b :: hd. So that means that eventually when we pass it a list with n elements, it will recursively work on a list with n-1 elements, n-2 elements, etc. But eventually it will have one element. And there is no case for that. So we need to add a case for the one element pattern:
let rec helper = function
| [] -> []
| h :: [] -> h :: []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)
I'm a beginner in F# and I'm trying to write a function to subset a dictionary given list, and return the result.
I tried this, but it doesn't work.
let Subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = dict.Clear
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.TryGetValue k) )
|> List.iter (fun s -> z.Add s)
|> List.iter (fun s -> z.Add s);;
--------------------------------------^^^
stdin(597,39): error FS0039: The field, constructor or member 'Add' is not defined
Perhaps there is a native function in F# to do that ?
thanks
EDIT
thanks to #TheInnerLight for his answer below
can you just educate me a bit more, and tell me how i should adapt that function if i want to return the original variable being modified ?
(of course it would be possible to go from where we call that function, call it with a temp variable, and reassign)
You have written:
let z = dict.Clear
z is of type unit->unit yet you are calling z.Add.
I suspect you want to write
let subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = Dictionary<'T,'U>() // create new empty dictionary
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.[k]) )
|> List.iter (fun s -> z.Add s)
z
TryGetValue is going to return something of type bool*'U in F#, which I suspect you don't want if already filtering by ContainsKey so you probably want to look up directly with dict.[k].
Note that Dictionary is a mutable collection so if you were to actually call dict.Clear(), it wouldn't return a new empty dictionary, it would mutate the existing one by clearing all elements. The immutable F# data structure usually used for key-value relationships is Map, see https://msdn.microsoft.com/en-us/library/ee353880.aspx for things you can do with Map.
Here is a map version (this is the solution I recommend):
let subset map subList =
subList
|> List.choose (fun k -> Option.map (fun v -> k,v) (Map.tryFind k map))
|> Map.ofList
Edit (in response to the question edit about modifying the input variable):
It's possible to update an existing dictionary using the destructive update operator <- on a mutable variable.
Option 1:
let mutable dict = Dictionary<Key,Value>() // replace this with initial dictionary
let lst = [] // list to check against
dict <- sublist dict lst
Likewise, my first function could be changed to perform only a side effect (removing unwanted elements).
Option 2:
let subset (d : System.Collections.Generic.Dictionary<'T,'U>) (sub_list : list<'T>) =
sub_list
|> List.filter (d.ContainsKey >> not)
|> List.iter (d.Remove >> ignore)
For an F# beginner I don't really recommend Option 1 and I really don't recommend Option 2.
The functional approach is to favour immutable values, pure functions, etc. This means you will be better off thinking of your functions as defining data transformations rather than as defining a list of instructions to be performed.
Because F# is a multi-paradigm language, it's easy to fall back on the imperative in the early stages but you will probably gain the most from learning your new language if you force yourself to adopt the standard paradigm and idioms of that language even if those idioms feel strange and uncomfortable to begin with.
The immutable data structures like Map and list are pretty efficient at sharing data as well as providing good time complexity so these are really the go-to collections when working in F#.
fighting with f# - the fight is in the realm of Trees - specifically to count the number of nodes. This is of real interest as the program I would like to eventually code in F# concerns multi-way trees, unfortunately it has got off to a bit of a troublesome start - I hope you maybe able to help!
Problem 61 of the 99 f# series, asks to count the leaves of a binary Tree. The solution (given below) counts the nodes, but my problem is not understanding
how the double recursion works loop left (fun lacc -> loop right..)
what cont (branchF x lacc racc) is, my impression was that cont was the "abc" function, but this takes only two parameters...
loop t id the id is of type unit - i don't see how this is implied
basically not understanding this, or the order in which it flows through the tree (debug & step through not proving helpful) If there are simpler examples, pre-reading recommendations etc. then please direct me to them.
Many thanks for any help, the solution code in question is below:
Cheers
td
type 'a Tree = Empty | Branch of 'a * 'a Tree * 'a Tree
let foldTree branchF emptyV t =
let rec loop t cont =
match t with
| Empty ->
cont emptyV
| Branch (x, left, right) ->
loop left (fun lacc ->
loop right (fun racc ->
cont (branchF x lacc racc)))
loop t id
let counLeaves tree =
foldTree (fun abc lc rc ->
if lc + rc = 0 then 1
else 1 + lc + rc) 0 tree
let Tree1 = Branch ('x', Branch ('x', Empty, Empty),Branch ('x', Empty, Branch ('x', Empty, Branch ('x', Empty, Empty))))
let result = counLeaves Tree1
As the name implies, foldTree defines the fold function over the custom Tree type.
A naive way of defining a foldTree could be:
let rec foldTreeNaive accFun init = function
| Empty -> init
| Branch (x, left, right) ->
let lacc = foldTreeNaive accFun init left
let racc = foldTreeNaive accFun init right
accFun x lacc racc
The problem with this function is that it could potential make very deep recursive calls if the tree being folded over is deep, since the recursive calls must complete for a node before the accumulator function can be called. For example the following causes a stack overflow exception:
let unbalanced = [1..100000] |> List.fold (fun t i -> Branch(i, t, Empty)) Empty
let nodeCount = foldTreeNaive (fun _ lc rc -> lc + rc + 1) 0 unbalanced
The usual way to avoid such stack overflows is to make the function tail recursive, however this seems impossible in this case since there are two recursive calls to make, instead of the one required when folding over lists.
foldTree is defined using the local loop function. This function is interesting in that it is defined using continuation passing style. In CPS, each function takes an additional 'continuation' function which is passed the result of the computation and is responsible for deciding what happens next. Note that loop is tail recursive and so avoids the overflow problem of foldTreeNaive.
The type of the loop function is:
Tree<'a> -> ('b -> 'c) -> 'c
where 'a is the type of nodes in the tree, 'b is the accumulator type, and 'c is the result of the continuation function.
In the case of a leaf node, the continuation is passed the empty accumulator value passed to the foldTree function.
When folding over a non-empty tree in the Branch case, the result of the fold depends on the results for the left and right subtrees. This is done recursively, first by folding over the left subtree, then the right. For the recursive call over the left subtree, loop must build a new continuation to receive the result, this is the
(fun lacc ->
loop right (fun racc ->
cont (branchF x lacc racc))
function. What this continuation does is to make a recursive call over the right subtree, passing yet another continuation to receive the result of that fold. When that continuation is called, the results for the left and right subtrees are available in lacc and racc. At this point the accumulation function for the node can be called with the value for the current node and the results for the left and right subtrees. The result of this function is then passed to the original continuation passed to loop.
The loop function is then invoked by the foldTree function in the line:
loop t id
Here, id is the continuation which will receive the result of the fold for the root node of the tree. Since this is the value required, id just returns its argument without modification.
You might also find this description of fold for binary trees useful.