I am trying to get this example translated from C# to F#
public class MyModule : NancyModule
{
private IMyDependency _dependency;
public MyModule(IMyDependency dependency)
{
_dependency = dependency;
Get["/"] = x =>
{
};
// Register other routes
}
}
(source 1)
However adding a parameter to constructor
type HelloModule(dependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
(source 2)
results in a run-time exception: System.InvalidOperationException: 'Something went wrong when trying to satisfy one of the dependencies during composition ...
How can I correctly add a dependency like a data-source to the code? Or, generally, how do I pass something from outside of HelloModule to the inside?
I'm guessing this might be caused by not specifying the type of the dependency parameter of the constructor in your F# code. This would result in the F# compiler assigning that parameter a generic type, and then Nancy's dependency injection framework doesn't know what to inject.
Try the following and see if it fixes your problem:
type HelloModule(dependency : IMyDependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
P.S. Naturally, for this to work, you'll also need to have some type that implements the IMyDependency interface, and have told the Nancy framework about that type. From this part of the Nancy documentation that you linked to, it looks like merely declaring the type is enough, but if that's not actually enough then you'll have to register the type manually. I'm not familiar enough with Nancy to give you specific advice there beyond what the documentation says.
Related
What is the expected way to extend a class imported from a Javacript library while at the same being capable to call parent's members?
I tried several alternatives, using abstract classes apparently worked without errors but the child cannot call parent's abstract method, with interfaces there were no errors either but I cannot call to parent's class as there is no reference.
The best method I found is the following one overriding the mezhods, and althought the yielt code works, the compiler still emits an error:
error FSHARP: No abstract or interface member was found that corresponds to this override (code 855)
My current code:
[<Import("DataManager", from="library/data")>]
type DataManager<'Model> (conf:obj) =
class
member this.insert(_:'Model):Promise<obj> = jsNative
member this.update (_:'Model):Promise<obj> = jsNative
end
type MyAdaptor<'Model> (conf, inst)=
inherit DataManager<'Model> (conf)
let DB:obj = inst
do
printf "I've been created"
override this.insert(o:'Model):Promise<obj> =
printf "insert method comes with object:"
console.log o
base.insert o
//Constructors.Promise.Create o
override this.update(o:'Model): Promise<obj> =
printf "Update method comes with object:"
console.log o
base.update o
//Constructors.Promise.Create o
Previously I also tried to use just members and still call base's method but althought it compiled without issue, when calling instance's methods only parent's code was executed. I am afraid it might be a bug.
I also had several tries callint the inheritance manually in a self-made constructor but it usually fails to compile because the imported JS was either not recognize as a valid constructor or then I couldn't include the method definitions (I care about type safety).
It turns out that in F# people cannot override a method which has not been declared previously as abstract.
For that the solution was to declare the methods as abstract and provide a default implementation before override.
[<Import("DataManager", from="library/data")>]
type DataManager<'Model> (conf:obj) =
class
abstract member insert: 'Model -> Promise<obj>
default this.insert(_:'Model):Promise<obj> = jsNative
abstract member update:'Model -> Promise<obj>
default this.update (_:'Model):Promise<obj> = jsNative
end
After that it is possible to override the child class without issues.
I can't get this piece of code to pass.
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.Verify(fun m -> m.Add(It.IsAny<string>()), Times.Once())
Exception I get:
System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
I believe it has something to do with F# not inferring properly the data type of labda expression but I don't know how to fix that.
You are correct, this an issue with F# type inference when calling an overloaded method that accepts either Action or Func.
One option is to download the Moq.FSharp.Extensions from Nuget and change your Verify to an explicit VerifyAction, i.e.
open Moq.FSharp.Extensions
type MyTests() =
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.VerifyAction((fun m -> m.Add(any())), Times.Once())
Underneath the covers the Moq.FSharp.Extensions simply defines an extension method VerifyAction that only takes an Action to avoid ambiguity:
type Moq.Mock<'TAbstract> when 'TAbstract : not struct with
member mock.VerifyAction(expression:Expression<Action<'TAbstract>>) =
mock.Verify(expression)
Another option is to use Foq, a mocking library with a similar API to Moq but designed specifically for use from F#, also available via Nuget:
[<Test>]
member public this.Test() =
let mock = Mock.Of<IList<string>>()
mock.Add("aaa")
Mock.Verify(<# mock.Add(any()) #>, once)
Let's say we have the following C# class
public class Class1
{
protected event EventHandler ProtectedEvent;
protected virtual void OverrideMe() { }
}
It seems to be impossible to use the ProtectedEvent in F#.
type HelpMe() as this =
inherit Class1()
do
printfn "%A" this.ProtectedEvent
member x.HookEvents() =
printfn "%A" x.ProtectedEvent
member private x.HookEvents2() =
printfn "%A" x.ProtectedEvent
override x.OverrideMe() =
printfn "%A" x.ProtectedEvent
In this example I have attempted to call printfn on it, as there are multiple ways to hook up events in F# and I wanted to be clear that is simply the referencing of the event at all that causes the problem.
In each of the cases above the compiler complains with the following error
A protected member is called or 'base' is being used. This is only
allowed in the direct implementation of members since they could
escape their object scope.
I understand this error, what causes it and its purpose. Usually, the work around is to wrap the call in a private member, which works fine with methods - but that does not seem to work with events. No matter what I try, it seems to be impossible to use protected events in F# unless I resort to doing something with reflection, or make some changes to the base class (which in my case is not possible).
Note that I have also tried all possible combinations of using base, this and x.
Am I doing something wrong ?
I suspect that there is something about the code that the compiler generates behind the scene when you treat the event as a first-class value that later confuses it (i.e. some hidden lambda function that makes the compiler think it cannot access the protected member). I'd say that this is a bug.
As far as I can see, you can workaround it by using add_ProtectedEvent and remove_ProtectedEvent members directly (they do not show in the auto-completion, but they are there and are accessible - they are protected, but calling them is a direct method call, which is fine):
type HelpMe() =
inherit Class1()
member x.HookEvents() =
let eh = System.EventHandler(fun _ _ -> printfn "yay")
x.add_ProtectedEvent(eh)
override x.OverrideMe() =
printfn "hello"
This compiled fine for me. It is a shame that you cannot use the protected event as a first-class value, but this at least lets you use it...
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.
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#).