recently I started my adventure with F#. I'm trying to create F# library that I will use in my C# projects.
Now I'm facing the problem that I have two types definitions that (as I wish) could use themselves (I'm trying to create fluent API for c# usage).
How I want to use it in c# (simplified example).
Shopping shopping = new Shopping();
Stuff[] stuff = shopping.GoTo("Wallmart").Buy(new [] { "Candies", "Ice cream", "Milk" }).GoTo("Drug store").Buy(new [] { "Anvil" }).GetStuff();
Now I have two types (in separted files):
type ShopResult(someContext: ShoppingContext) =
//some logic
member this.GoTo shopName = new ToDoResult(someContext)
type ToDoResult(someContext: ShoppingContext) =
//some logic
member this.Buy what = new ShopResult(someContext)
Now the file order causing compilation error and I'm wondering if there's any solution for my case? or have I to drop the fluent api idea?
Put both types in the same file and change the definitions to the following:
type ShopResult(someContext: ShoppingContext) =
//some logic
member this.GoTo shopName = new ToDoResult(someContext)
and ToDoResult(someContext: ShoppingContext) =
//some logic
member this.Buy what = new ShopResult(someContext)
For more information, see the section 'Mutually Recursive Types' in the language reference on MSDN.
Related
I am totally newbie in F# and I am trying to create an object that contains aonother instance from other class. For me in C# it's quite easy, but in F# I have serious problems to understand it.
Here is my code
module Owe
type Owe= class
val Name: string
val Amount: float
new (name, amount) as this =
{
Name = name
Amount = amount
}
end
And this is the class that I want to instace using the Owe object…. but, I can't invoque the Owe attribute.
module Roomate
type Roomate = class
val Name : string
val Owe: module.Owe //Error!
new(name, owe) as this =
{
Name = name
Owe = owe
}
end
I reallay apreciate any advice or solution.
Thanks in advance.
Emma.
You are probably getting an error because module.Owe is not a correct way of referencing a type from another module. You do not need the module keyword here - you just need to give the module name and the class name as in <module-name>.<class-name>. In your case, somewhat confusingly, both the module name and the class name are Owe so you can write Owe.Owe.
Another thing to keep in mind is that, in F#, the order of files matters. This means that you can only reference classes from files that appear earlier in your project.
Finally, I would also add that it is quite common to declare multiple types in one file (and in one module) in F#, so you do not need to move your definitions into separate files. I would also recommend using the lightweitght syntax for declaring classes using implicit constructors:
type Owe(name:string, amount:float) =
member x.Name = name
member x.Amount = amount
type Roomate(name:string, owe:Owe) =
member x.Name = name
member x.Owe = owe
Although in this case, you might not need classes at all and you could probably just use records:
type Owe = { Name:string; Amount:float }
type Roomate = { Name:string; Owe:Owe }
The FSharp.Data.JsonProvider provides a means to go from json to an F# type. Is it possible to go in the reverse direction i.e. declare an instance of one of the types created by FSharp.Data.JsonProvider, set the field values to be what I need, and then get the equivalent json?
I've tried things like this,
type Simple = JsonProvider<""" { "name":"John", "age":94 } """>
let fred = Simple(
Age = 5, // no argument or settable property 'Age'
Name = "Fred")
The latest version of F# Data now supports this. See the last example in http://fsharp.github.io/FSharp.Data/library/JsonProvider.html.
Your example would be:
type Simple = JsonProvider<""" { "name":"John", "age":94 } """>
let fred = Simple.Root(age = 5, name = "Fred")
This is one area where C# has an edge over F#, at least in Visual Studio. You can copy your JSON example code into the clipboard and in Visual Studio use the Edit -> Paste Special -> Paste JSON As Classes and it will create a class to match the JSON example. From there you can easily use the class in F#.
More details on paste special here
Hopefully a matching feature will come for F# soon too.
I have a create a Wcf Service using WcfPortal.It exposes basic method Fetch,Delete,Insert and Update. I use this Service in my MVC project as below
ServiceReference2.WcfPortalClient obj = new ServiceReference2.WcfPortalClient();
Application App = new Application();
var AppType = App.GetType();
ApplicationCriteria Criteria = new ApplicationCriteria {ApplicationName = "application" };
ServiceReference2.FetchRequest Fetch1 = new ServiceReference2.FetchRequest();
CslaTest.ServiceReference2.DataPortalContext context = new ServiceReference2.DataPortalContext();
Fetch1._context = context;
Fetch1._objectType= AppType;
Fetch1._criteria = Criteria;
var list = obj.Fetch(Fetch1);
But when i compile my project i get error as:
Type 'CslaTest.BusinessLibrary.ApplicationCriteria' with data contract name
ApplicationCriteria:http://schemas.datacontract.org/2004/07/CslaTest.BusinessLibrary' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'
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 am trying to create two types where one is able to remove itself from the other such as in this example.
type employee (workplace : Job) =
member this.Fire () = workplace.Employees.Remove(this) |> ignore
and Job () =
let employees = new ResizeArray<employee>()
member this.Employees = employees
But this gets me the compile error of "Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved."
I'm not sure what I am doing wrong here. Any help would be appreciated
You can solve the problem even without reordering the declarations - when the F# compiler type-checks the Employee declaration, it doesn't yet know what is the type of workplace.Employees (because the type hasn't been declared yet), so it doesn't know where does the Remove method come from. You can correct that by adding type annotation that specifies that Employees is ResizeArray<Employee>:
type Employee (workplace : Job) =
member this.Fire () =
let emps : ResizeArray<Employee> = workplace.Employees
emps.Remove(this) |> ignore
and Job () =
let employees = new ResizeArray<Employee>()
member this.Employees = employees
However, this example isn't very functional - if you're going to use mutable state (such as ResizeArray), then the state should be hidden as private state of the type (so Jobs could have a Remove method).
In general, declaring recursive type declarations is a bit less comfortable in F# - however, you shouldn't need them that often. Quite frequently, you can use more generic types (i.e. Job may not need to know abou the Employee type).
Try this..
type Job () =
let employees = new ResizeArray<employee>()
member this.Employees = employees
and employee (workplace : Job) =
member this.Fire () = workplace.Employees.Remove(this) |> ignore