Building Code Expressions "Manually" - f#

I want to construct a F# code expression. However I dont want to do that via code quotations but construct it via objects.
However the documentation on how to do that is pretty scarce.
Given the following snippet
type Foo = { foo = string}
let bar = {foo = "foo"}
let ex = <# bar.foo #>
this yields for ex.
PropertyGet (Some (ValueWithName ({foo = "foo";}, bar)), foo, [])
But I simply cant replicate that exact term above. For example I dont find anything on the constructor ValueWithName.
So how can I
<# bar.foo #> = PropertyGet (Some (ValueWithName ({foo = "foo";}, bar)), foo, [])

Using the library to construct quotations manually is quite difficult to do correctly, so I'd highly recommend using quotation literals wherever you can. However, here's how to achieve your example if you want to:
open Microsoft.FSharp.Quotations
Expr.PropertyGet(
Expr.ValueWithName({ foo = "foo" }, "bar"),
typeof<Foo>.GetProperty("foo"))

Related

Is there a way to use let statements in classes with inline methods?

A simplified example that gives an error because let str is private:
let launch = printfn "%s"
type Test() =
let str = "Hello"
member inline t.A() =
launch str
I've discovered statically resolved type parameters in F# and after a rewrite have a neural net library where 95% of the functions are inlined as a result, including class methods. I wrote it as a F# script at first, forgetting that there is a difference between script mode and compiled mode in their treatment of inlined methods.
let test = // Is this the only choice?
let str = "Hello"
fun () ->
launch str
Is there any way to use body initializers in F# classes or should I rewrite the classes to be higher order functions like the above? Thankfully, that would not be a problem here.
This question is related to this one, but I thought I'd ask again since it has been 5 years.
Actually I was wrong. It is true that the higher order function example does work in the simplified case above, but I've realized that lambda arguments cannot be statically resolved. I thought of using records for a bit and then tried this:
type Test() =
let str = "Hello"
member t.Str = str
member inline t.A() =
launch t.Str
Private member can be exposed and this will compile. Doing it like the above would be satisfactory.

How to get a reference to a function that doesn't take parameters in F#?

I sometimes have the need to get the function itself, not the value, of a zero-parameter function in F#, for instance for memoization. I.e., I have this:
let memoize (f: 'a -> 'b) =
let dict = new Dictionary<'a, 'b>()
let memoizedFunc (input: 'a) =
match dict.TryGetValue(input) with
| true, x -> x
| false, _ ->
let answer = f input
dict.Add(input, answer)
answer
memoizedFunc
and this works perfectly, but now I have the following function:
let private getDataSlowOperation =
// implementation
and when I try to memoize that, it gives a type mismatch (essentially the mismatch between the return type of getDataSlowOperation and the 'a type). I can solve this by changing the function as follows:
let private getDataSlowOperation bogus =
// implementation
Now this works, but it seems odd to have to change the function signature to get memoization to work:
let memoGetDataSlowOperation = memoize getDataSlowOperation
I've experimented with inline fun declarations, but this creates, of course, a new anonymous function and the memoization doesn't work with that. Any ideas how to resolve this? Any keyword / operator I've forgotten about?
What you defined is not a function, it's just a value.
In order to define it as a function you can write this:
let private getDataSlowOperation() =
// implementation
UPDATE
To summarize the discussion:
This is the right way to write it as a function, however the code would still not work but that's a different problem.
The code would fail at runtime because () is compiled to null and by using a Dictionary you can't use null for the Key. You can use a Map instead.
John pointed out that memoization for functions without parameters makes no sense, I agree.
Still, if you use a Dictionary for functions with parameters you will run into the same problem with values that are compiled to null, ie: None

Alternatives to functors in F#

I would like to write the following:
module A =
type Token
let foo Token =
module B =
type Token
let foo Token =
let run (m : module) =
m.B
|> m.foo
basically a function that's generic in the module. Is there a way to do this in F#?
As kvb pointed out in a comment, it is hard to give an answer without a realistic example, because the best approach will depend on what you're actually trying to do.
In this trivial example, I would probably use F# interface to represent Token and add Foo as a member. Assuming that Foo returns an int, you can write the definition like this:
type Token =
abstract Foo : unit -> int
Then you can implement different tokens either using classes (which is quite heavyweight) or using object expressions. For example:
let tok = { new Token with
member x.Foo () = 42 }
The code that corresponds to your run function is just a call of the Foo member: tok.Foo()

Formatting fluent/method chaining code from C# in F#

Some apis like Ninject use fluent style apis, example:
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(x => x.DoSomething())
When I try format the code like this in F# the compiler complains at the whitespace between method calls.
Is it possible to put the method calls on seperate lines? I was thinking something like the pipelining operator |> but not exactly sure how in this case.
How should this be formatted in F#?
Are you sure this doesn't work?
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
(note one space before the .s)
Yeah, it's fine:
type ISomething = interface end
type Something = class end
type Foo() =
member this.To<'a>() = this //'
member this.WithConstructorArgument(s1,s2) = this
member this.OnActivation(x:Foo->unit) = this
member this.DoSomething() = ()
let Bind<'a>() = new Foo() //'
let r =
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
So long as you have some leading whitespace when you try to continue a single expression onto multiple lines, you're ok.
(Note that pipelining in general won't work unless you have APIs designed for it with curried method parameters.)

How do you use (get values from keys, add items) Hashtables in F#

I would like to know how to use a System.Collections.Hashtable in F#. The reason it is a Hashtable is because I am referencing C# assemblies.
How would I call the following methods?
- Add
- Get value from key
I have not been able to find anything useful in Google about this.
As Mark points out, you can work with the Hashtable type directly from F# (just like with any other .NET type). The syntax for accessing indexers in F# is slightly different though:
open System.Collections
// 'new' is optional, but I would use it here
let ht = new Hashtable()
// Adding element can be done using the C#-like syntax
ht.Add(1, "One")
// To call the indexer, you would use similar syntax as in C#
// with the exception that there needst to be a '.' (dot)
let sObj = ht.[1]
Since Hashtable is not generic, you would probably want to cast the object back to string. To do that, you can either use the :?> downcast operator, or you can use the unbox keyword and provide a type annotation to specify what type do you want to get as the result:
let s = (sObj :?> string)
let (s:string) = unbox sObj
If you have any control over what type is used, then I would recommend using Dictionary<int, string> instead of Hashtable. This is fully compatible with C# and you would avoid the need to do casting. If you're returning this as a result from F#, you could also use standard F# map and just upcast it to IDictionary<_,_> before passing it to C#:
let map = Map.empty |> Map.add 1 "one"
let res = map :> IDictionary<_, _>
This way, C# users will see a familiar type, but you can write the code in the usual functional style.
It's pretty straightforward to do.
open System.Collections //using System.Collections
let ht = Hashtable() // var ht = new Hashtable()
ht.Add(1, "One")
let getValue = ht.Item[1] // var getValue = ht[1];
//NB: All indexer properties are named "Item" in F#.

Resources