How to use Named Arguments in F#
Asked Answered
M

1

7

Calling a Dictionary's Add() method using named arguments works in F#.

let d = Dictionary<string, obj>()
d.Add(key = "five", value = 5)

let d2= Dictionary<obj, obj>()
d2.Add(key = "five", value = 5)
d2.Add(key = 5, value = 5)

In Polly's Context class , there is a similar Add() method with 2 overloads:

Add(key: obj, value: obj) : unit
Add(key: string, value: obj) : unit

And I can use it in all of these ways:

let c = Polly.Context()
c.Add("five", 5)
c.Add(5, 5)
c.Add(key = 5, value = 5)

But not this way, it says it can't resolve between the overloads and needs a type annotation.

c.Add(key = "five", value = 5)

Why is that and how can I fix it?

Millard answered 13/7, 2018 at 1:22 Comment(0)
A
9

The compiler cannot work out which method to use. This is more common when dealing with C# and OO style in general with F#. I don't mind, keeps me functionally honest.

The most straightforward way to fix your problem now would be to use:

c.Add(key = ("five" :> obj), value = 5)

By casting it there is no ambiguity about what the type is and the compiler is happy.

Alternatively, you could create a function with explicit types and this will help the compiler figure it out as well. If you are using this a lot I suggest this:

let addToPolly (ctx:Polly.Context) (k:obj) (v:obj) =
        ctx.Add(k,v)
        ignore()

addToPolly c "five" 5

UPDATE: As @brett pointed out I had inferred the answer but not been explicit. Here are some examples where the compiler is happy.

let pollyAddAsString (ctx:Polly.Context) (k:string) (v:obj) = ctx.Add(key = k, value = v) |> ignore
let pollyAddAsObj (ctx:Polly.Context) (k:obj) (v:obj) = ctx.Add(key = k, value = v) |> ignore
pollyAddAsObj c "five" 5
pollyAddAsString c "five" 5

let (k:string,v:obj) = ("five", 5 :> obj)
let (x:obj,y:obj) = ("five" :> obj, 5 :> obj)
c.Add(key = k, value = v)
c.Add(key = x, value = y)
Adlay answered 13/7, 2018 at 4:10 Comment(5)
This is a great answer for the obj, obj overload. How about the string,obj overload?Millard
Good point point @BrettRowberry. I have updated my answer. I hope this helps. Please let me know if not.Adlay
Is there a particular reason you NEED to use the named arguments?Adlay
This is great stuff. We can create helper functions as you did with pollyAddAsString/pollyAddAsObj or by creating and deconstructing tuples as you did with (k,v)/(x,y).Millard
F# is my favorite language. I never NEED to use named arguments in .NET, but I like them for resolving ambiguity. I first learned about 'named parameters' from Objective-C/Swift. When I learned they could optionally be included in .NET, I was very excited. The benefit of named parameters at the call site of a method is similar to the benefit records have over tuples. Records and tuples have pretty much the same capabilities, but the labels make it easier to read the code, especially when multiple parameters/arguments are distinguished by order because they have the same type.Millard

© 2022 - 2024 — McMap. All rights reserved.