f# type providers and INPC metaprogramming - f#

I read the following article
http://studentguru.gr/b/kron/archive/2012/09/26/c-template-metaprogramming-and-f-type-providers.aspx
which shows a way to do compile time Fibonacci sequence generation with F# Type providers. The solution is in the article but the final program is
> cat .\fib.fs
type fib = Playground.StaticFibonacci<100000>
printfn "Fibonacci(100000) has %d digits" fib.Value.Length
> fsc .\fib.fs -o fib.exe -r:.\FibonacciTypeProvider.dll –nologo
> .\fib.exe
Fibonacci(100000) has 20899 digits
This look very powerful. I was wondering if it would be possible to create a type provider for INPC ( INotifyPropertyChanged ) such that you instead of
open System.ComponentModel
type MyObject() =
let mutable propval = 0.0
let propertyChanged = Event<_, _>()
interface INotifyPropertyChanged with
[<clievent>]
member x.PropertyChanged = propertyChanged.Publish
member this.MyProperty
with get() = propval
and set(v) =
propval <- v
propertyChanged.Trigger(this, new PropertyChangedEventArgs("MyProperty"))
You might be able to write
open System.ComponentModel
type MyObject() =
let mutable propval = 0.0
let propertyChanged = Event<_, _>()
interface INotifyPropertyChanged with
[<clievent>]
member x.PropertyChanged = propertyChanged.Publish
member this.MyProperty : INPCTypeProvider<double>
So before I waste half a day digging into this perhaps somebody more informed could tell me I am wasting my time and this level of meta programming is just not possible.

I do not think you can achieve this with F# type providers (but I can see that that it would be nice). There is a number of problems and thoughts I can think of:
In your example, your INPCTypeProvider<double> would have to return something like a representation of a "property". This is not possible, because properties are not first-class values (unlike events). If they were, you wouldn't need a type provider...
Type provider cannot be parameterized by an existing type, so you cannot write say:
type MyNotifyObject = ProvideNotifiable<MyObject>
If this was possible, ProvideNotifiable could be a provider taking a type and building a new type with additional interface implementation. But this is not possible at the moment.
If you only need simple types, you might be able to create something like:
type MyObject = ProvideNotifiable<"MyProperty:int, OtherProperty:string">
This could generate a type with the two properties (defined in the string), but you cannot add anything more to the generated type (although, you might be able to generate actual type using generative provider and inherit from it...) I think this is probably the best you can do.
Aside from type providers, you can simplify the implementation of INotifyPropertyChanged a bit by using quotations. This F# snippet gives a simple example that makes the implementation safer.

Related

What would be the inferred type of my function here?

I am wondering why F# compiler allows the following
type MyMath() =
member this.Add a b = a + b
What would be the type of Add method and its arguments ? If I compiled this into the Library and try to use it in C# what types of arguments it is going to expect ?
Shouldn't the F# require you to explicitly specify types when it comes to Methods of classes ?
You can enter the code in F# interactive and see the inferred type yourself:
> type MyMath() =
member this.Add a b = a + b;;
type MyMath =
class
new : unit -> MyMath
member Add : a:int -> b:int -> int
end
Here, the compiler uses default type for the + operator which is int. The operator can be used with other types, but the inference uses int as the default. You can use type annotations, but you are not required to do that if you are happy with the inferred type.
In general, you can use type annotations in F# to specify types if you want to, but in many cases, the inferred type will be exactly what you want, so you do not have to make the code more verbose, if the inference behaves as expected.
Of course, if you were writing some library and wanted to be super careful about changing the API, then you might want to use type annotations (or you can add F# Interface file .fsi)
F# Interactive is your friend:
type MyMath =
class
new : unit -> MyMath
member Add : a:int -> b:int -> int
end

Is there a way to inject support for the F# Option type into ServiceStack?

Updated below...
I recently started experimenting with ServiceStack in F#, so naturally I started with porting the Hello World sample:
open ServiceStack.ServiceHost
open ServiceStack.ServiceInterface
open ServiceStack.WebHost.Endpoints
[<CLIMutable; Route("/hello"); Route("/hello/{Name}")>]
type Hello = { Name : string }
[<CLIMutable>]
type HelloResponse = { Result : string }
type HelloService() =
inherit Service()
member x.Any(req:Hello) =
box { Result = sprintf "Hello, %s!" req.Name }
type HelloAppHost() =
inherit AppHostBase("Hello Web Services", typeof<HelloService>.Assembly)
override x.Configure container = ()
type Global() =
inherit System.Web.HttpApplication()
member x.Application_Start() =
let appHost = new HelloAppHost()
appHost.Init()
That works great. It's very concise, easy to work with, I love it. However, I noticed that the routes defined in the sample allow for the Name parameter to not be included. Of course, Hello, ! looks kind of lame as output. I could use String.IsNullOrEmpty, but it is idiomatic in F# to be explicit about things that are optional by using the Option type. So I modified my Hello type accordingly to see what would happen:
[<CLIMutable; Route("/hello"); Route("/hello/{Name}")>]
type Hello = { Name : string option }
As soon as I did this, the F# type system forced me to deal with the fact that Name might not have a value, so I changed HelloService to this to get everything to compile:
type HelloService() =
inherit Service()
member x.Any(req:Hello) =
box { Result =
match req.Name with
| Some name -> sprintf "Hello, %s!" name
| None -> "Hello!" }
This compiles, and runs perfectly when I don't supply a Name parameter. However, when I do supply a name...
KeyValueDataContractDeserializer: Error converting to type: Type
definitions should start with a '{', expecting serialized type
'FSharpOption`1', got string starting with: World
This wasn't a complete surprise of course, but it brings me to my question:
It would be trivial for me to write a function that can wrap an instance of type T into an instance of type FSharpOption<T>. Are there any hooks in ServiceStack that would let me provide such a function for use during deserialization? I looked, but I couldn't find any, and I'm hoping I was just looking in the wrong place.
This is more important for F# use than it might seem at first, because classes defined in F# are by default not allowed to be null. So the only (satisfying, non-hacky) way of having one class as an optional property of another class is with, you guessed it, the Option type.
Update:
I was able to sort-of get this working by making the following changes:
In the ServiceStack source, I made this type public:
ServiceStack.Text.Common.ParseFactoryDelegate
...and I also made this field public:
ServiceStack.Text.Jsv.JsvReader.ParseFnCache
With those two things public, I was able to write this code in F# to modify the ParseFnCache dictionary. I had to run this code prior to creating an instance of my AppHost - it didn't work if I ran it inside the AppHost's Configure method.
JsvReader.ParseFnCache.[typeof<Option<string>>] <-
ParseFactoryDelegate(fun () ->
ParseStringDelegate(fun s -> (if String.IsNullOrEmpty s then None else Some s) |> box))
This works for my original test case, but aside from the fact that I had to make brittle changes to the internals of ServiceStack, it sucks because I have to do it once for each type I want to be able to wrap in an Option<T>.
What would be better is if I could do this in a generic way. In C# terms, it would be awesome if I could provide to ServiceStack a Func<T, Option<T>> and ServiceStack would, when deserializing a property whose generic type definition matches that of the return type of my function, deserialize T and then pass the result into my function.
Something like that would be amazingly convenient, but I could live with the once-per-wrapped-type approach if it were actually part of ServiceStack and not my ugly hack that probably breaks something somewhere else.
So there are a couple of extensibility points in ServiceStack, on the framework level you can add your own Custom Request Binder this allows you to provide your own model binder that's used, e.g:
base.RequestBinders.Add(typeof(Hello), httpReq => {
var requestDto = ...;
return requestDto;
});
But then you would need to handle the model binding for the different Content-Types yourself, see CreateContentTypeRequest for how ServiceStack does it.
Then there are hooks at the JSON Serializer level, e.g:
JsConfig<Hello>.OnDeserializedFn = dto => newDto;
This lets you modify the instance of the type returned, but it still needs to be the same type but it looks like the F# option modifier changes the structural definition of the type?
But I'm open to adding any hooks that would make ServiceStack more palatable for F#.
What does the code look like to generically convert a normal Hello type to an F# Hello type with option?
The only thing I can think of is to replace the option type with your own type, one that has an implicit conversion from string to myOption, and anything else you need.
Not all that nice, but workable. Your type would probably also need to be serializable.
type myOption =
| None
| Some of string
static member public op_Implicit (s:string) = if s <> null then Some s else None
member public this.Value = match this with
| Some s -> s
| _ -> null
member this.Opt = match this with
| Some s -> Option.Some s
| None -> Option.None
Your record type would then be
[<CLIMutable>]
type Hello =
{ Name : myOption }
On the other hand, ServiceStack is open source, so maybe something could be done there.

F# mutable with no initial value for MEF

I have a bunch of modules that export an IModule interface. So in the main program I have no problems
...
let mutable modules = Seq.empty
[<ImportMany>]
member x.Modules
with get():IEnumerable<Lazy<IModule, IModuleData>> = modules
and set(a) = modules <- a
...
But now I need to expose an interface back to those modules. So each module will import a single interface
...
let mutable parent:IParent = ?
[<Import>]
member x.Parent
with get():IParent = parent
and set(a) = parent <- a
...
So my problem is how do I go about creating my mutable "parent" when I have no initial value for it? Also, is this the appropriate way to expose an API back to component parts?
Using Unchecked.defaultof<_> should do the trick, but it means that you're circumventing the F# type system, which may be a dangerous thing to do - the system tries to prevent you from accidentally dereferencing null values (and getting NullReferenceException).
Types that are declared in F# don't have null as a proper value, which is an attempt to eliminate the usual errors caused by null. The clean F# approach is to use option types to represent the fact that a value is missing:
let mutable parent:option<IParent> = None
[<Import>]
member x.Parent
with get():IParent =
match parent with
| Some p -> p
| None -> failwith "TODO: Throw some reasonable exception here!"
and set(a) = parent <- Some(a)
If you just want to say that IParent can have a null value (perhaps because you need to use it in some C# code that will ignore the F# restriction anyway), then you can mark the type definition using a special attribute that allows using null with the type.
[<AllowNullLiteral>]
type IParent =
abstract DoStuff : unit -> unit
Then you can write let mutable parent:IParent = null. The benefit of this approach is that you can also easily check whether a value is null (using just if parent <> null then ...) which is not that obvious when you use Unchecked.defaultof<_>.
let mutable parent = Unchecked.defaultof<IParent>
should do the trick.
Following up on what Tomas explained, you should probably put your imports directly into your constructor. That will allow your code to be a bit more idiomatic.

why is the implementation of my abstract member not public

I've been struggling to get this to compile for about an hour. It must be something stupid. Can you spot it?
in my lib project:
namespace TravelerStuff
open System
type Traveler =
abstract GetData : unit -> unit
type public DeltaTraveler() =
interface Traveler with
member v.GetData () =
printf "hello"
and in my console test app:
[<EntryPoint>] let main _ =
let traveler = new TravelerStuff.DeltaTraveler()
traveler.GetData // this line won't compile: (The field, constructor or member 'GetData' is not defined)
As gradbot says, F# doesn't currently implicitly convert values to interfaces when searching for members. Also, F# only uses explicit interface implementation (as known from C#) and not implicit implementation where members are not only compiled as implementation of an interface, but also as ordinary (directly visible) members of the type.
Aside from casting, you can duplicate the member in the type definition:
type DeltaTraveler() =
member v.GetData () = printf "hello"
interface Traveler with
member v.GetData () = v.GetData()
Also, if you just want to implement an interface, but don't need to add any members, you can use F# object expressions (which are more lightweight):
let deltaTraveler() =
{ new Traveler with
member v.GetData () = printf "hello" }
// The function directly returns value of type 'Traveler'
let t = deltaTraveler()
t.GetData()
You need to upcast. F# currently won't do it for you in this situation.
(traveler :> TravelerStuff.Traveler).GetData()
// open the namespace to reduce typing.
open TravelerStuff
(traveler :> Traveler).GetData()
Snip from F# docs.
In many object-oriented languages,
upcasting is implicit; in F#, the
rules are slightly different.
Upcasting is applied automatically
when you pass arguments to methods on
an object type. However, for let-bound
functions in a module, upcasting is
not automatic, unless the parameter
type is declared as a flexible type.
For more information, see Flexible Types (F#).

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