Concisely creating an IDictionary<_,obj> - f#

Is there a shorter way of creating an IDictionary<_,obj>, possibly without boxing every value? This is what I have.
let values =
[ "a", box 1
"b", box "foo"
"c", box true ]
|> dict
Dictionary<_,obj>.Add can be called without boxing, but I couldn't figure out a way to use it that's shorter than what I have.
I'm hoping for something other than defining a boxing operator.
EDIT
Based on Brian's suggestion, here's one way to do it, but it has its own problems.
let values =
Seq.zip ["a"; "b"; "c"] ([1; "foo"; true] : obj list) |> dict

Here's a solution, following kvb's suggestion (probably the most concise, and clearest, so far):
let inline (=>) a b = a, box b
let values =
[ "a" => 1
"b" => "foo"
"c" => true ]
|> dict

Here's the slickest thing I was able to whip up. It has more characters than your boxing version, but possibly feels a little less dirty. Note that the ^ is right-associative (it's the string concat operator inherited from ocaml), which lets it work like ::, and it has stronger precedence than ,, which is why the parenthesis are needed around the tuples.
let inline (^+) (x1:'a,x2:'b) (xl:('a*obj) list) =
(x1,box x2)::xl
let values =
("a", 1) ^+ ("b", "foo") ^+ ("c", true) ^+ []
|> dict

I had a similar problem in FsSql and I just tucked away boxing in a function:
let inline T (a,b) = a, box b
let values = dict [T("a",1); T("b","foo"); T("c",true)]

Here's another "solution" which is inspired from Brian's suggestion but it uses reflection so there is a time and safety cost.
let unboxPair (pair:obj) =
let ty = pair.GetType()
let x = ty.GetProperty("Item1").GetValue(pair,null) :?> string
let y = ty.GetProperty("Item2").GetValue(pair,null)
x,y
let unboxPairs (pairs:obj list) =
pairs |> List.map unboxPair
let values =
unboxPairs
["a", 1
"b", "foo"
"c", true]
|> dict

A variation of Stephen's idea:
open System
open System.Collections.Generic
type Dictionary<'a,'b> with
member this.Add([<ParamArray>] args:obj[]) =
match args.Length with
| n when n % 2 = 0 ->
for i in 1..2..(n-1) do
this.Add(unbox args.[i-1], unbox args.[i])
| _ -> invalidArg "args" "even number of elements required"
let d = Dictionary<string,obj>()
d.Add(
"a", 1,
"b", "foo",
"c", true
)

Yet another solution, simply define a bunch of overloaded extension members on Dictionary<'a,'b>:
open System.Collections.Generic
type Dictionary<'a,'b> with
member this.Add(x1,y1,x2,y2) =
this.Add(x1,y1)
this.Add(x2,y2)
member this.Add(x1,y1,x2,y2,x3,y3) =
this.Add(x1,y1,x2,y2)
this.Add(x3,y3)
member this.Add(x1,y1,x2,y2,x3,y3,x4,y4) =
this.Add(x1,y1,x2,y2,x3,y3)
this.Add(x4,y4)
member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5) =
this.Add(x1,y1,x2,y2,x3,y3,x4,y4)
this.Add(x5,y5)
member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6) =
this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5)
this.Add(x6,y6)
//etc.
let values =
let d = Dictionary<_,obj>()
d.Add("a", 1,
"b", "foo",
"c", true)
d
Of course values here is not immutable like in your question, but I'm sure you could employ the same strategy in that goal.

let v : (string*obj) list = [...]
let values = dict v
Is one way, the type signature on the left of the list literal will auto-upcast each element.

Related

(F#) Inbuilt function to filter a list if it does not contain a specific value

My question is regarding list filtering in F#. Is there a built in function that allows the filtering of lists where it only returns those that do not satisfy a condition?
let listOfList = [ [1;2;3;4;5]; [6;7;8;9;10]; [11;2;5;14;1] ]
let neededValue = 1
I know that F# features List.Contains() however I want to only return lists which do not satisfy the condition.
let sortedLists = listOfList |> List.filter(fun x -> x <> x.Contains(neededValue)
This obviously does not work because in this instance I'm comparing a list to whether a list contains a specific value. How would I do this? My desired output in this instance would be:
sortedLists = [ [6;7;8;9;10] ]
You were so close! Change x <> to not <|, and it will work.
let listOfList = [ [1;2;3;4;5]; [6;7;8;9;10]; [11;2;5;14;1] ]
let neededValue = 1
let sortedLists = listOfList |> List.filter(fun x -> not <| x.Contains(neededValue))
The not function allows you to negate a boolean value, so that the types in the filter expression match up.
In f# it's more idiomatic to use
List.contains neededValue x
instead of
x.Contains(neededValue)
So I would express it like this
let sortedLists =
listOfList
|> List.filter (List.contains neededValue >> not)

Is a pattern match the only way to get data associated with a union case?

Let's say you have this union:
type Thing =
| Eagle
| Elephant of int
And your code has a list of Elephants, as in
let l = [Elephant (1000); Elephant (1200)]
And you wanted to iterate over l, and print out the data associated with each Elephant. Is there a way to do so without using a pattern match?
In your example, you say that you have a list of elephants - which is true in this case - but the type of l is really a list of Thing values and so it can contain both elephants and eagles. This is why you need to use pattern matching - to handle all possible cases.
If you regularly need to use list that contain only elephants, then it might make sense to define a separate type of elephants. Something like:
type ElephantInfo = { Size : int }
type Thing =
| Elephant of ElephantInfo
| Eagle
Now you can create a list of type list<ElephantInfo> which can contain just elephants and so you don't need pattern matching:
let l1 = [ {Size=1}; {Size=2} ]
for el in l1 do printfn "%d" el.Size
On the other hand, if you want to mix elephants and eagles, you'll create list<Thing> and then use pattern matching:
let l2 = [ Elephant {Size=1}; Eagle ]
You could do this:
l
|> List.collect (function Elephant x -> [x] | _ -> [])
|> List.iter (printfn "%i")
Prints
1000
1200
It still uses pattern matching, but it's fairly minimal.
You have of course the option of going full Ivory Tower (® Scott Wlaschin)
As in about:
type Thing =
| Eagle
| Elephant of int
type MaybeElephantBuilder() =
member this.Bind(x, f) =
match x with
| Eagle -> 0
| Elephant a -> f a
member this.Return(x) = x
let maybeElephant = new MaybeElephantBuilder()
let l =
[ Elephant(1000)
Elephant(1200)
]
let printIt v =
let i =
maybeElephant {
let! elephantValue = v
return elephantValue
}
printfn "%d" i
l |> Seq.iter printIt
It will even handle the stuff with the Eagles thrown in there!
Well...
Remove the non-Eagles and the code will fly...
let l =
[ Eagle
Leadon
Elephant(1000)
Eagle
Meisner
Elephant(1200)
Eagle
Felder
]
l |> Seq.iter printIt
But no. Its not nice. Its not short. Its more for fun (if that!) than anything else. Its probably the worst misuse of F# computation expressions ever too!
And you will need pattern matching somewhere.
Thx Scott! And Petricek.
Computation Expression Zoo for real! ;-)
You can use reflection from Microsoft.FSharp.Reflection Namespace but it is much more cumbersome and slow.
Pattern matching is probably the easiest way to get data from discriminated union.
(Also you have a list of Things all its members happen to be of Elephant union case).
There's a way to place the pattern match into the header of the function (or a let binding). It is still a pattern match, though.
// This function takes a tuple:
// the first argument is a Thing,
// the second is "default" weight to be processed if the first one is NOT an Elephant
let processElephant (Elephant weight, _ | _, weight) =
weight
let [<Literal>] NON_ELEPHANT_WEIGHT = -1
// usage:
let totalWeight =
[Elephant (1000); Elephant (1200)]
|> List.sumBy (fun el -> processElephant(el, NON_ELEPHANT_WEIGHT))
This question and its answers provide with more details.

Completely lost in trying to mutate property in sequence

I am completely at loss why this code doesn't mutate a member variable in a sequence of types:
for p in prescrs do
p.ATC <- "A"
for c in p.Drug.Components do
for s in c.Substances do
s.DoseTotal.Adjust <- adjustKg
s.DoseTotal.Time <- "DAY"
s.DoseTotal.Unit <- s.DrugConcentration.Unit
s.DoseRate.Adjust <- adjustKg
s.DoseRate.Time <- "DAY"
s.DoseRate.Unit <- s.DrugConcentration.Unit
prescrs is a sequence of Prescriptions which is a very simple 'POCO' defined as a type with member values. I don't have clue why this doesn't work.
I tried a simple test case like:
type IterTest () =
member val Name = "" with get, set
member val IterTests = [] |> List.toSeq : IterTest seq with get, set
let iterseq =
[
new IterTest(Name = "Test1")
new IterTest(Name = "Test2")
]
|> List.toSeq
iterseq |> Seq.iter(fun x -> x.IterTests <- iterseq)
iterseq |> Seq.iter(fun x ->
x.IterTests
|> Seq.iter(fun x' -> x'.Name <- "itered"))
But here the result is as expected. So, can't even quite reproduce my problem???
Found a solution (without really understanding the problem above). When I first convert the prescrs sequence to a list like:
let prescrs = prescrs |> Seq.toList
and then do the imperative looping, properties do get mutated.
Try this sample:
type Mutable() =
member val Iterated = false with get, set
let muts = Seq.init 5 (fun _ -> printfn "init"; Mutable())
let muts2 = muts // try again with let muts2 = muts |> List.ofSeq
printfn "Before iter"
for a in muts2 do
printfn "iter"
a.Iterated <- true
printfn "After iter"
muts2 |> List.ofSeq
and check how iter and init are interleaved.
Seqs are lazy, but are not cached once computed. So even if you imperatively try to mutate some of the elements in your prescrs sequence, it all goes away once you pull prescrs again. If you change prescrs into a concrete collection type like list before doing the mutation, you no longer hit the same problem. Note that things might get even trickier if what you have is a seq inside a seq inside a seq.
The best idea would be to avoid mutation in the first place though.

error with f# generic follow Expert Fsharp book example

I'm reading Expert F# book and I found this code
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
and the example use:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
first for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang..specially compared to clojure. But the problem is not this...I'm having problems with the Dictionary definition
when I type this:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
I get this:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
is It ok?...
thanks so much
improve question:
Ok I've been reading about value restriction and I found this helpfull information
In particular, only function definitions and simple immutable data
expressions are automatically generalized
...ok..this explains why
let dict = new Dictionary<'key,ResizeArray<'T>>();;
doesn't work...and show 4 different techniques, although in my opinion they only resolve the error but aren't solutions for use generic code:
Technique 1: Constrain Values to Be Nongeneric
let empties : int list [] = Array.create 100 []
Technique 3: Add Dummy Arguments to Generic Functions When Necessary
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
Technique 4: Add Explicit Type Arguments When Necessary (similar to tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- and the only one than let me use real generic code ------
Technique 2: Ensure Generic Functions Have Explicit Arguments
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
Ok, in 3 of 4 techniques I need resolve the generic code before can work with this...now...returning to book example...when the compile knows the value for 'key and 'T
let dict = new Dictionary<'key,ResizeArray<'T>>()
in the scope the code is very generic for let key be any type, the same happen with 'T
and the biggest dummy question is :
when I enclose the code in a function (technique 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
for me (admittedly I'm a little dummy with static type languages) this is not real generic because it can't infer the type when I use it, I need define the type and then pass values (not define its type based in the passed values) exist other way define type without be so explicit..
thanks so much..really appreciate any help
This line
let dict = new Dictionary<'key,ResizeArray<'T>>();;
fails because when you type the ;; the compiler doesn't know what 'key and 'T are. As the error message states you need to add a type annotation, or allow the compiler to infer the type by using it later or make it a function
Examples
Type annotation change
let dict = new Dictionary<int,ResizeArray<int>>();;
Using types later
let dict = new Dictionary<'key,ResizeArray<'T>>()
dict.[1] <- 2
using a function
let dict() = new Dictionary<'key,ResizeArray<'T>>();;
This actually doesn't cause an issue when it's defined all together. That is, select the entire block that you posted and send it to FSI in one go. I get this:
val divideIntoEquivalenceClasses :
('T -> 'key) -> seq<'T> -> seq<'key * seq<'T>> when 'key : equality
However, if you type these individually into FSI then as John Palmer says there is not enough information in that isolated line for the interpreter to determine the type constraints. John's suggestions will work, but the original code is doing it correctly - defining the variable and using it in the same scope so that the types can be inferred.
for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang.
I agree completely – it's slightly tangential to your direct question, but I think a more idiomatic (functional) approach would be:
let divideIntoEquivalenceClasses keyf seq =
(System.Collections.Generic.Dictionary(), seq)
||> Seq.fold (fun dict v ->
let key = keyf v
match dict.TryGetValue key with
| false, _ -> dict.Add (key, ResizeArray(Seq.singleton v))
| _, prev -> prev.Add v
dict)
|> Seq.map (function KeyValue (k, v) -> k, Seq.readonly v)
This allows sufficient type inference to obviate the need for your question in the first place.
The workarounds proposed by the other answers are all good. Just to clarify based on your latest updates, let's consider two blocks of code:
let empties = Array.create 100 []
as opposed to:
let empties = Array.create 100 []
empties.[0] <- [1]
In the second case, the compiler can infer that empties : int list [], because we are inserting an int list into the array in the second line, which constrains the element type.
It sounds like you'd like the compiler to infer a generic value empties : 'a list [] in the first case, but this would be unsound. Consider what would happen if the compiler did that and we then entered the following two lines in another batch:
empties.[0] <- [1] // treat 'a list [] as int list []
List.iter (printfn "%s") empties.[0] // treat 'a list [] as string list []
Each of these lines unifies the generic type parameter 'a with a different concrete type (int and string). Either of these unifications is fine in isolation, but they are incompatible with each other and would result in treating the int value 1 inserted by the first line as a string when the second line is executed, which is clearly a violation of type safety.
Contrast this with an empty list, which really is generic:
let empty = []
Then in this case, the compiler does infer empty : 'a list, because it's safe to treat empty as a list of different types in different locations in your code without ever impacting type safety:
let l1 : int list = empty
let l2 : string list = empty
let l3 = 'a' :: empty
In the case where you make empties the return value of a generic function:
let empties() = Array.create 100 []
it is again safe to infer a generic type, since if we try our problematic scenario from before:
empties().[0] <- [1]
List.iter (printfn "%s") (empties().[0])
we are creating a new array on each line, so the types can be different without breaking the type system.
Hopefully this helps explain the reasons behind the limitation a bit more.

F# collection initializer syntax

What is the collection initializer syntax in F#? In C# you can write something like:
new Dictionary<string, int>() {
{"One", 1},
{"two", 2}}
How do I do the same thing in F#? I suppose i could roll my own syntax, but seems like there should be a built-in or standard one already.
To elaborate a bit on collection initialization in F#, here are a few examples:
read-only dictionary
dict [ (1, "a"); (2, "b"); (3, "c") ]
seq (IEnumerable<T>)
seq { 0 .. 99 }
list
[1; 2; 3; 4; 5]
set
set [1; 2; 3; 4; 5]
array
[| 1; 2; 3; 4; 5 |]
As Jared says, there is no built-in support for this for arbitrary collections. However, the C# code is just syntactic sugar for Add method calls, so you could translate it to:
let coll = MyCollectionType()
["One", 1; "Two", 2] |> Seq.iter coll.Add
If you want to get fancy, you could create an inline definition to streamline this even further:
let inline initCollection s =
let coll = new ^t()
Seq.iter (fun (k,v) -> (^t : (member Add : 'a * 'b -> unit) coll, k, v)) s
coll
let d:System.Collections.Generic.Dictionary<_,_> = initCollection ["One",1; "Two",2]
I don't believe F# has an explicit collection initializer syntax. However it's usually very easy to initialize F# collections. For example
let map = [ ("One", 1); ("Two", 2) ] |> Map.ofSeq
Getting to BCL collections is usually a bit more difficult because they don't always have the handy conversion functions. Dictionary<TKey, TValue> works though because you can use the LINQ method
let map =
let list = [ ("One", 1); ("Two", 2) ]
System.Linq.Enumerable.ToDictionary(list, fst, snd)
You can use the same :
open System.Collections.Generic
Dictionary<int, string>(dict [ (1, "a"); (2, "b"); (3, "c") ])
Cheers.
The lack of a collection initializer is annoying for some XAML-centric APIs like Workflow 4.0 which rely on collection initializers instead of ctors, e.g.
new Sequence { Activities = { WriteLine { Text = "In the sequence!" } } };
In such cases, imperative .Add() is awkward because the value is conceptually declarative even though it's technically mutable/imperative. However, there's no common base class for the set of all activities which declare an Activities child: the "Activities" member is a pattern and not an interface, so you can't just write a normal helper function which adds children to any activity. Fortunately, F# member constraints come to the rescue.
In order to write this:
Sequence() |> add [Sequence(DisplayName="InnerSeq"); WriteLine(Text = InArgument<_>("In the sequence!"))]
You first need to define an inline helper function called "add":
let inline add (children: Activity seq) =
let inline doAdd (activity: ^Activity) : ^Activity when ^Activity : (member get_Activities : unit -> Activity Collection) =
let collection = (^Activity : (member get_Activities : unit -> Activity Collection) (activity))
for child in children do
collection.Add(child)
activity
doAdd
This still isn't quite as nice as the C# syntax but at least it's still declarative. IMHO this is not so much as a fault with F# as with collection-initializer-centric APIs, but at least F# allows a workaround.
Given that the C# collection initializer syntax is syntactic sugar for calling .Add and that implies a mutable collection - I'm not sure you'll see any such syntax in F#. It's initialize all in one go as per JaredPar's answer, or do it manually.

Resources