Synchronization of SortedDictionary.iteri using readlock and writelock - f#

let info = new SortedDictionary<string, string>
...
Thread A
--------
info.Add("abc", "def")
Thread B
--------
info
|> Seq.iteri (fun i value -> ...
Where do I place the readLock when I use the iteri function?

You may want to just side-step the problem of mutability, and use an immutable Map instead of SortedDictionary. This way, your iteration works on a "snapshot" of the data structure, with no worries about it getting changed out from underneath you. Then, you only need to lock your initial grab of the snapshot.
For example (warning, have not tested to see if this is actually threadsafe!):
let mymap = ref Map<string,string>.Empty
let safefetch m = lock(m) (fun () -> !m)
let safeadd k v m = lock(m) (fun () -> m := Map.add k v !m)
mymap
|> safefetch
|> Map.iter ( fun k v -> printfn "%s: %s" k v )
mymap |> safeadd "test" "value"

After some thinking it seems that placing a lock on Seq.iteri does actually make no sense since a Seq is lazy in F#.
However it is interesting to note that an exception is thrown when additional elements of a dictionary are inserted by another thread during the iteration of the sequence. Not sure if that is fully warranted for a lazy iteration.
My solution (as a function) right now is:
(fun _ ->
lock info (fun _ ->
info
|> Seq.iteri (fun i x -> ...)))
I hope it is OK to answer my own question (I am new here).

Related

List of Dictionary's vs Sequence of Dictionary's

I am having trouble understanding the difference between F#'s List and Seq in this example. I thought that the main difference was that Seq was kind of lazy, but I must be missing something.
This code snippet:
open System.Collections.Generic
let arr =
["a"; "b"; "c"]
|> Seq.map (fun a -> let dic = Dictionary () in dic.Add("key", a); dic) in
arr
|> Seq.iter (fun a ->
printfn "here";
a.["key"] <- "something"
);
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
Gives
here
here
here
a
b
c
Whereas (replacing the first Seq with List)
open System.Collections.Generic
let arr =
["a"; "b"; "c"]
|> List.map (fun a -> let dic = Dictionary () in dic.Add("key", a); dic) in
arr
|> Seq.iter (fun a ->
a.["key"] <- "something"
);
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
Gives
something
something
something
Why do the Dictionary values not change when I use Seq? The elements are clearly visited as the here is printed.
Thanks in advance.
The reason is precisely that Seq is "kind of lazy", as you put it.
It's "lazy" in the sense that it gets evaluated every single time you ask it to. All of it. Up to the last non-lazy thing.
In particular, the call to Seq.map is lazy. It does not create a new structure in memory that is full of dictionaries. Instead, it creates something that you could call a "pipeline". This pipeline starts with your list ["a"; "b"; "c"] and then there is an instruction: every time somebody tries to iterate over this sequence, create a new dictionary for every element. The "every time" bit is important there - since you're iterating over the sequence twice (once to print "here" and another time to print the values), the dictionaries get created twice as well. The dictionary into which you push "something" and the dictionary from which you obtain "key" are not the same dictionary.
To illustrate further, try this:
let s = ["a";"b";"c"] |> Seq.map( fun x -> printfn "got %s" x; x )
s |> Seq.iter(printfn "here's %s")
s |> Seq.iter(printfn "again %s")
This will print the following:
got a
here's a
got b
here's b
got c
here's c
got a
again a
got b
again b
got c
again c
See how the "got" output happens twice for each element? That's because Seq.map works every time you iterate, not just once.
Not so with lists. Every time you List.map, you create a whole new list in memory. It just sits there forever (where "forever" is defined "until garbage collector gets to it") and waits for you to do something with it. If you do multiple things with it, it's still the same list, it doesn't get re-created. That is why your dictionaries are always the same dictionaries, they don't get created anew, like the ones in Seq. That is why you can modify them and see the modifications next time you look.
You can achieve a similar, though not quite identical effect with sequences with the help of Seq.cache. This function takes a regular on-demand-evaluating sequence and returns you a sequence that is identical, except every element only gets evaluated once.
Unlike a list though, Seq.cache will not evaluate the whole sequence the moment it's called. Instead, it will create a mutable cache, which gets updated every time you evaluate.
This is useful for cases when a sequence is very large, or even infinite, but you only need to work with a small finite number of elements at the start of it.
Illustration:
let s = ["a";"b";"c"]
|> Seq.map( fun x -> printfn "got %s" x; x )
|> Seq.cache
s |> Seq.iter(printfn "here's %s")
s |> Seq.iter(printfn "again %s")
Output:
got a
here's a
got b
here's b
got c
here's c
again a
again b
again c
I added some printfns to both examples so you can see the difference:
let arr =
["a"; "b"; "c"]
|> Seq.map (fun a -> printfn "seq: %s" a
let dic = Dictionary ()
dic.Add("key", a)
dic)
arr
|> Seq.iter (fun a ->
printfn "here seq"
a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
produces the following output:
seq: a
here seq
seq: b
here seq
seq: c
here seq
seq: a
a
seq: b
b
seq: c
c
While this one:
let arr =
["a"; "b"; "c"]
|> List.map (fun a -> printfn "list: %s" a
let dic = Dictionary ()
dic.Add("key", a)
dic)
arr
|> Seq.iter (fun a ->
printfn "here list";
a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
produces this output:
list: a
list: b
list: c
here list
here list
here list
something
something
something
As you can see the behavior is quite different.
Seq.map is lazy which means it remains as a function to be invoked later only when strictly necessary. Every time it is invoked it starts from the beginning mapping each element as they are needed. Seq.map gets called twice, one for each Seq.iter and every time it creates a new Dictionary for each element which then is discarded by the garbage collector.
On the other hand, List.map gets invoked only once and it goes over the whole input list creating a new list of dictionaries only one time.

Merging two lists in F#

I wrote this function which merges two lists together but as I'm fairly new to functional programming I was wondering whether there is a better (simpler) way to do it?
let a = ["a"; "b"; "c"]
let b = ["d"; "b"; "a"]
let merge a b =
// take all a and add b
List.fold (fun acc elem ->
let alreadyContains = acc |> List.exists (fun item -> item = elem)
if alreadyContains = true then
acc
else
elem :: acc |> List.rev
) b a
let test = merge a b
Expected result is: ["a"; "b"; "c"; "d"], I'm reverting the list in order to keep the original order. I thought I would be able to achieve the same using List.foldBack (and dropping List.rev) but it results in an error:
Type mismatch. Expecting a
'a
but given a
'a list
The resulting type would be infinite when unifying ''a' and ''a list'
Why is there a difference when using foldBack?
You could use something like the following
let merge a b =
a # b
|> Seq.distinct
|> List.ofSeq
Note that this will preserve order and remove any duplicates.
In F# 4.0 this will be simplified to
let merge a b = a # b |> List.distinct
If I wanted to write this in a way that is similar to your original version (using fold), then the main change I would do is to move List.rev outside of the function (you are calling List.rev every time you add a new element, which is wrong if you're adding even number of elements!)
So, a solution very similar to yours would be:
let merge a b =
(b, a)
||> List.fold (fun acc elem ->
let alreadyContains = acc |> List.exists (fun item -> item = elem)
if alreadyContains = true then acc
else elem :: acc)
|> List.rev
This uses the double-pipe operator ||> to pass two parameters to the fold function (this is not necessary, but I find it a bit nicer) and then passes the result to List.rev.

fold or choose till None?

Is there already a way to do something like a chooseTill or a foldTill, where it will process until a None option is received? Really, any of the higher order functions with a "till" option. Granted, it makes no sense for stuff like map, but I find I need this kind of thing pretty often and I wanted to make sure I wasn't reinventing the wheel.
In general, it'd be pretty easy to write something like this, but I'm curious if there is already a way to do this, or if this exists in some known library?
let chooseTill predicate (sequence:seq<'a>) =
seq {
let finished = ref false
for elem in sequence do
if not !finished then
match predicate elem with
| Some(x) -> yield x
| None -> finished := true
}
let foldTill predicate seed list =
let rec foldTill' acc = function
| [] -> acc
| (h::t) -> match predicate acc h with
| Some(x) -> foldTill' x t
| None -> acc
foldTill' seed list
let (++) a b = a.ToString() + b.ToString()
let abcdef = foldTill (fun acc v ->
if Char.IsWhiteSpace v then None
else Some(acc ++ v)) "" ("abcdef ghi" |> Seq.toList)
// result is "abcdef"
I think you can get that easily by combining Seq.scan and Seq.takeWhile:
open System
"abcdef ghi"
|> Seq.scan (fun (_, state) c -> c, (string c) + state) ('x', "")
|> Seq.takeWhile (fst >> Char.IsWhiteSpace >> not)
|> Seq.last |> snd
The idea is that Seq.scan is doing something like Seq.fold, but instead of waiting for the final result, it yields the intermediate states as it goes. You can then keep taking the intermediate states until you reach the end. In the above example, the state is the current character and the concatenated string (so that we can check if the character was whitespace).
A more general version based on a function that returns option could look like this:
let foldWhile f initial input =
// Generate sequence of all intermediate states
input |> Seq.scan (fun stateOpt inp ->
// If the current state is not 'None', then calculate a new one
// if 'f' returns 'None' then the overall result will be 'None'
stateOpt |> Option.bind (fun state -> f state inp)) (Some initial)
// Take only 'Some' states and get the last one
|> Seq.takeWhile Option.isSome
|> Seq.last |> Option.get

F# Pipelines access data from pipeline stages above

I have written a function like this
let GetAllDirectAssignmentsforLists (spWeb : SPWeb) =
spWeb.Lists
|> Seq.cast<SPList>
|> Seq.filter(fun l -> l.HasUniqueRoleAssignments)
|> Seq.collect (fun l -> l.RoleAssignments
|> Seq.cast<SPRoleAssignment>
|> Seq.map(fun ra -> ra.Member)
)
|> Seq.filter (fun p -> p.GetType().Name = "SPUser")
|> Seq.map(fun m -> m.LoginName.ToLower())
I want to return a tuple which contains the list name (taken from l.Title) in the send pipe and the m.LoginName.ToLower().
Is there a cleanway for me to get something from the above pipe elements?
One way ofcourse would be to tuple the return value in the 2nd stage of the pipe and then pass the Title all the way down.... but that would pollute the code all subsequent stages will then have to accept and return tuple values just for the sake of the last stage to get the value.
I wonder if there is a clean and easy way....
Also, in stage 4 of the pipeline (fun p -> p.GetType().Name = "SPUser") could i use if here to compare the types? rather than convert the typename to string and then match strings?
We exploit the fact that Seq.filter and Seq.map can be pushed inside Seq.collect without changing the results. In this case, l is still available to access.
And the last filter function is more idiomatic to use with type test operator :?.
let GetAllDirectAssignmentsforLists(spWeb: SPWeb) =
spWeb.Lists
|> Seq.cast<SPList>
|> Seq.filter (fun l -> l.HasUniqueRoleAssignments)
|> Seq.collect (fun l -> l.RoleAssignments
|> Seq.cast<SPRoleAssignment>
|> Seq.map (fun ra -> ra.Member)
|> Seq.filter (fun p -> match box p with
| :? SPUser -> true
| _ -> false)
|> Seq.map (fun m -> l.Title, m.LoginName.ToLower()))
To simplify further, you could change the series of Seq.map and Seq.filter to Seq.choose:
Seq.choose (fun ra -> match box ra.Member with
| :? SPUser -> Some (l.Title, ra.Member.LoginName.ToLower())
| _ -> None)
While you can solve the problem by lifting the rest of the computation inside collect, I think that you could make the code more readable by using sequence expressions instead of pipelining.
I could not run the code to test it, but this should be equivalent:
let GetAllDirectAssignmentsforLists (spWeb : SPWeb) = seq {
// Corresponds to your 'filter' and 'collect'
for l in Seq.cast<SPList> spWeb.Lists do
if l.HasUniqueRoleAssignments then
// Corresponds to nested 'map' and 'filter'
for ra in Seq.cast<SPRoleAssignment> l.RoleAssignments do
let m = ra.Member
if m.GetType().Name = "SPUser" then
// This implements the last 'map' operation
yield l.Title, m.LoginName.ToLower() }
The code above corresponds more closely to the version by #pad than to your original code, because the rest of the computation is nested under for (which corresponds to nesting under collect) and so you can see all variables that are already in scope - like l which you need.
The nice thing about sequence expressions is that you can use F# constructs like if (instead of filter), for (instead of collect) etc. Also, I think it is more suitable for writing nested operations (which you need here to keep variables in scope), because it remains quite readable and keeps familiar code structure.

Complex Continuation in F#

All of the continuation tutorials I can find are on fixed length continuations(i.e. the datastructure has a known number of items as it is being traversed
I am implementing DepthFirstSearch Negamax(http://en.wikipedia.org/wiki/Negamax) and while the code works, I would like to rewrite the code using continuations
the code I have is as follows
let naiveDFS driver depth game side =
List.map (fun x ->
//- negamax depth-1 childnode opposite side
(x, -(snd (driver (depth-1) (update game x) -side))))
(game.AvailableMoves.Force())
|> List.maxBy snd
let onPlay game = match game.Turn with
| Black -> -1
| White -> 1
///naive depth first search using depth limiter
let DepthFirstSearch (depth:int) (eval:Evaluator<_>) (game:GameState) : (Move * Score) =
let myTurn = onPlay game
let rec searcher depth game side =
match depth with
//terminal Node
| x when x = 0 || (isTerminal game) -> let movescore = (eval ((),game)) |> fst
(((-1,-1),(-1,-1)),(movescore * side))
//the max of the child moves, each child move gets mapped to
//it's associated score
| _ -> naiveDFS searcher depth game side
where update updates a gamestate with a with a given move, eval evaluates the game state and returns an incrementer(currently unused) for incremental evaluation and isTerminal evaluates whether or not the position is an end position or not.
The Problem is that I have to sign up an unknown number of actions(every remaining list.map iteration) to the continuation, and I actually can't conceive of an efficient way of doing this.
Since this is an exponential algorithm, I am obviously looking to keep this as efficient as possible(although my brain hurts trying to figure this our, so I do want the answer more than an efficient one)
Thanks
I think you'll need to implement a continuation-based version of List.map to do this.
A standard implementation of map (using the accumulator argument) looks like this:
let map' f l =
let rec loop acc l =
match l with
| [] -> acc |> List.rev
| x::xs -> loop ((f x)::acc) xs
loop [] l
If you add a continuation as an argument and transform the code to return via a continuation, you'll get (the interesting case is the x::xs branch in the loop function, where we first call f using tail-call with some continuation as an argument):
let contMap f l cont =
let rec loop acc l cont =
match l with
| [] -> cont acc |> List.rev
| x::xs -> f x (fun x' -> loop (x'::acc) xs cont)
loop [] l cont
Then you can turn normal List.map into a continuation based version like this:
// Original version
let r = List.map (fun x -> x*2) [ 1 .. 3 ]
// Continuation-based version
contMap (fun x c -> c(x*2)) [ 1 .. 3 ] (fun r -> ... )
I'm not sure if this will give you any notable performance improvement. I think continuations are mainly needed if you have a very deep recursion (that doesn't fit on the stack). If it fits on the stack, then it will probably run fast using stack.
Also, the rewriting to explicit continuation style makes the program a bit ugly. You can improve that by using a computation expression for working with continuations. Brian has a blog post on this very topic.

Resources