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 }
Related
Just curious why F# has:
member val Foo = ... with get, set
While omitting the self identifier (e.g. this.).
This is still an instance property. Maybe I am the only one confused when using it. But just bothered me enough to query whoever knows how the language was defined.
With this syntax, the property is almost totally auto-implemented -- all you provide is the initialization code, which essentially runs as part of the constructor.
One of the best-practice guard rails F# puts in place is that it does not let you access instance members before the instance is fully initialized. (wow, crazy idea, right?).
So you would have no use for a self-identifier in auto-props, anyways, since the only code you get to write is init code that can't touch instance members.
Per the MSDN docs (emphasis mine):
Automatically implemented properties are part of the initialization of
a type, so they must be included before any other member definitions,
just like let bindings and do bindings in a type definition. Note that
the expression that initializes an automatically implemented property
is only evaluated upon initialization, and not every time the property
is accessed. This behavior is in contrast to the behavior of an
explicitly implemented property. What this effectively means is that
the code to initialize these properties is added to the constructor of
a class.
Btw, if you try to be a smartass and use the class-level self-identifier to get around this, you'll still blow up at runtime:
type A() as this =
member val X =
this.Y + 10
with get, set
member this.Y = 42
let a = A()
System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.FailInit()
at FSI_0013.A.get_Y()
at FSI_0013.A..ctor()
at <StartupCode$FSI_0014>.$FSI_0014.main#()
Edit: Worth noting that in upcoming C# 6, they also now allow auto-props with initializers (more F# features stolen for C#, shocker :-P), and there is a similar restriction that you can't use the self-identifier:
class A
{
// error CS0027: Keyword 'this' is not available in the current context
public int X { get; set; } = this.Y + 10;
public int Y = 42;
public A() { }
}
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
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#).
In Haskell, I use the Data.Map module, and its principal type of the same name, Data.Map.Map, like this:
import Data.Map (Map)
import qualified Data.Map as M
In F#, I want to do something similar with my Item module, which contains a type of the same name:
module Item
type Item = { Description: string }
let empty = { Description = "" }
I can't find a way to use this module qualified and the type unqualified. Can I use this module and type like this, from another module?
let getItem (): Item = Item.empty
Edit:
Adding a type alias from a client module lets me use the Item module with qualification and the Item type without qualification, but is there a better way still?
type Item = Item.Item
I think the only way to import only a single type from a module is to use type alias (as you already noted). To get a qualified access to members of the module (under a different name), you can use module alias:
type Item = Item.Item // Type-alias for type(s) from module
module I = Item // Module-alias for accessing members
// Now you can write:
let getItem() : Item = I.empty
I don't think there is any way for importing members from module selectively (as in Haskell), so this is probably the best option.