7 people like it.
Like the snippet!
Creating named parameters
The snippet shows how to define the "=>" operator in F# so that it can be used for creating named parameters for dynamic API.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
|
// This does not work - no automatic conversion to 'obj'
let objs1 = [1; "hi"]
// ...but it works if compiler knows the type in advance
let objs2 : obj list = [1; "hi"]
// But, that only works for simple types - so even if we
// know the type in advance, it will not work for tuples :-(
let objs2 : (string*obj) list = [("hi", 1)]
// We could define our own tuple type to make this possible
// with a less generic base class - here, I just make base
// class generic in key, but not in value
type Tuple<'K> =
abstract Key : 'K
abstract Value : obj
// And then we have fully generic tuple that implements the
// less-generic variant (and boxes the value)
type Tuple<'K, 'V> =
| KV of 'K * 'V
member x.Key = let (KV(k, v)) = x in k
member x.Value = let (KV(k, v)) = x in v
interface Tuple<'K> with
member x.Key = let (KV(k, v)) = x in k
member x.Value = let (KV(k, v)) = x in box v
// Builds the more-generic version of the tuple
let (=>) k v = KV(k, v)
// This does not work, because we are creating list that
// contains 'Tuple<string, int>' and 'Tuple<string, string>'
let pars = ["x" => 1; "y" => "42"]
// But we can make it work if we know the type in advance
let namedPars (p:list<Tuple<string>>) = p
let pars = namedPars ["x" => 1; "y" => "42"]
// Note that this will NOT work
["x" => 1; "y" => "42"] |> namedPars
// It plays nicely with ParamArray too
type R() =
static member plot(s:string, [<System.ParamArray>] pars:Tuple<string>[]) =
printfn "%s - %A" s pars
// This gives us what Howard suggested!
R.plot("sin", "x" => 1, "y" => "42")
// But we can still write functions that require Tuple<string, int>
// rather than tuple with any type of values
let fromNums (nums:list<Tuple<string, int>>) = nums
// Fine
fromNums ["a" => 1; "b" => 3]
// Not allowed
fromNums ["a" => 1; "b" => 'a']
|
val objs1 : int list
Full name: Script.objs1
val objs2 : obj list
Full name: Script.objs2
type obj = System.Object
Full name: Microsoft.FSharp.Core.obj
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val objs2 : (string * obj) list
Full name: Script.objs2
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
type Tuple<'K> =
interface
abstract member Key : 'K
abstract member Value : obj
end
Full name: Script.Tuple<_>
abstract member Tuple.Key : 'K
Full name: Script.Tuple`1.Key
abstract member Tuple.Value : obj
Full name: Script.Tuple`1.Value
Multiple items
type Tuple<'K> =
interface
abstract member Key : 'K
abstract member Value : obj
end
Full name: Script.Tuple<_>
--------------------
type Tuple<'K,'V> =
| KV of 'K * 'V
interface Tuple<'K>
member Key : 'K
member Value : 'V
Full name: Script.Tuple<_,_>
union case Tuple.KV: 'K * 'V -> Tuple<'K,'V>
val x : Tuple<'K,'V>
member Tuple.Key : 'K
Full name: Script.Tuple`2.Key
val k : 'K
val v : 'V
member Tuple.Value : 'V
Full name: Script.Tuple`2.Value
override Tuple.Key : 'K
Full name: Script.Tuple`2.Key
override Tuple.Value : obj
Full name: Script.Tuple`2.Value
val box : value:'T -> obj
Full name: Microsoft.FSharp.Core.Operators.box
val k : 'a
val v : 'b
val pars : Tuple<string,int> list
Full name: Script.pars
val namedPars : p:Tuple<string> list -> Tuple<string> list
Full name: Script.namedPars
val p : Tuple<string> list
val pars : Tuple<string> list
Full name: Script.pars
type R =
new : unit -> R
static member plot : s:string * [<ParamArray>] pars:Tuple<string> [] -> unit
Full name: Script.R
static member R.plot : s:string * [<System.ParamArray>] pars:Tuple<string> [] -> unit
Full name: Script.R.plot
val s : string
namespace System
Multiple items
type ParamArrayAttribute =
inherit Attribute
new : unit -> ParamArrayAttribute
Full name: System.ParamArrayAttribute
--------------------
System.ParamArrayAttribute() : unit
val pars : Tuple<string> []
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
static member R.plot : s:string * [<System.ParamArray>] pars:Tuple<string> [] -> unit
val fromNums : nums:Tuple<string,int> list -> Tuple<string,int> list
Full name: Script.fromNums
val nums : Tuple<string,int> list
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
More information