F# What is the difference between the [<AbstractClass>] and [<AbstractClassAttribute>], both seem to label a type as abstract.
[<AbstractClass>]
https://msdn.microsoft.com/en-us/library/dd483471.aspx
[<AbstractClassAttribute>]
https://msdn.microsoft.com/en-us/library/ee370513.aspx
There is no difference, they both refer to AbstractClassAttribute. In F# (and C#), you can optionally omit the Attribute suffix when attaching an attribute with [<AttributeName>].
See: https://msdn.microsoft.com/en-us/library/dd233179.aspx#Anchor_1
Note that if you wished to refer to the attribute in normal code, you'd have to use the full name.
let example = AbstractClass() // ERROR
let example = AbstractClassAttribute() // OK
Related
If I write the following F# code, the compiler issues an error.
let a = 123
let a = 123
The error produced is:
error FS0037: Duplicate definition of value 'a'
If I write the same code in a function like this:
let fctn =
let a =123
let a =123
a
it doesn't produce any error.
I don't understand the difference. Can anyone please explain?
Edit : first code I write in module level.
I agree this is confusing. The problem is that let behaves differently when it is used as a local variable (within a function) and when it is used as a global definition (within a module).
Global definitions (in a module) are compiled as static members of a static class and so a name can be used only once. This means that top-level use of:
let a = 10
let a = 11
... is an error, because F# would have to produce two static members of the same name.
Local definitions (inside a function or some other nested scope) are compiled to Common IL and the variable name essentially disappears (the IL uses the stack instead). In this case, F# allows you to shadow variables, that is, you can hide a previous variable by re-using an existing name. This can be inside a function, or even just a do block inside a module, type or other function:
do
let a = 10
let a = 11
()
This is a bit confusing, because variable shadowing only works inside local scopes but not at the top level. It makes sense when you know how things are compiled though.
As an aside, while IL allows overloads of members by the same name, such overloads cannot be defined at module level in F#. Instead, you'd need to define them specifically as static member on a class (type in F#).
on scope and shadowing
as CaringDev mentioned (but not explained) you will probably see what the shadowing is about when you make the scope a bit more obvious (using the let ... in ... construct #light let you shorten a bit - but you still can use it even without #light off)
Try this:
> let a = 233 in let a = 555 in a;;
val it : int = 555
as you can see the expression evaluates to the shadowed value of a - but the original is not lost:
> let a = 233 in (let a = 555 in a), a;;
val it : int * int = (555, 233)
it's just not in scope in the inner let ... in ...
btw: you can rewrite your example to:
let fctn =
let a = 123 in
(let a =123 in a)
(I added the parentheses just to make this more obvious)
the other on the module level really defines a value for the scope of the module and is not really an expression but a definition
The first snippet defines two public values with the same name.
The second hides (shadows) a value.
With the first you would have externally visible change of state (a behaves like mutable) whereas with the second you can't (you have two as in different scopes).
If you write your statements in #light off ML syntax it becomes obvious immediately.
So I have been doing research on interfaces on F#. I have found these 2 articles on it. The MSDN and F# for fun and profit But unfortunately they are only skin deep.
UPDATED
here is my module with my interfaces
//open statements omitted for brevity
module DrawingInterfaces =
///gets a string representation of the SVG code representation of the object
type IRepresentable_SVG =
abstract member getSVGRepresenation : unit -> string
//other interfaces omitted for brevity
Now within the same namespace and physical folder also I have this:
type lineSet (x1off,x2off,y1off,y2off,x1,x2,y1,y2,rot,rotOff,count) =
//tons of member vals omitted for brevity
member val x1Start = x1 with get, set
interface DrawingInterfaces.IRepresentable_SVG with
member __.getSVGRepresenation() =
let mutable svg = ""
let mutable currentx1 = x1Start
svg
This used to give me 2 errors, before I was using the __. notation for the member. The first error was on the interface line. And a second on the member line.
The errors were respectively:
The type 'IRepresentable_SVG' is not defined
This instance member needs a parameter to represent the object being invoked.
I was able to fix the first one by changing the file order. Thanks to John Palmer.
The second one is nearly fixed./
After using the __ . notation I was able to get rid of the second error. However, now a new error pops up when I try to use type members in my interface implementation.
let mutable currentx1 = x1Start
x1Start shows as not being defined. I need to be able to use values stored in my other members within my implementation.
Let's first make it work and then point to your problems. I define below 2 separate modules in 2 separate .fs files within the same namespace Example for interface definition in module Example.DrawingInterfacesand interface implementation in module Example.UseInterface and also a console app that will use the interface from third (implicit) module Program. In my project correspondent code files are in the following order: DefInterface.fs, UseInterface,fs, Program.fs (I also made few idiomatic styling changes and more brevity omissions)
File: DefInterface.fs
namespace Example
module DrawingInterfaces =
type IRepresentable_SVG =
abstract member GetSVGRepresenation : unit -> string
File: UseInterface.fs
namespace Example
module UseInterface =
type LineSet (x1) =
member val X1Start = x1 with get, set
interface DrawingInterfaces.IRepresentable_SVG with
member __.GetSVGRepresenation() = "test" + " " + __.X1Start.ToString()
File: Program.fs
open Example
open System
[<EntryPoint>]
let main argv =
let lineSet = UseInterface.LineSet(5)
let example : DrawingInterfaces.IRepresentable_SVG = lineSet :> _
example.GetSVGRepresenation() |> printfn "%A"
lineSet.X1Start <- 10
example.GetSVGRepresenation() |> printfn "%A"
0
Compile, run and make sure it works.
Now to problems in your code:
first error message stems from the need to refer to the full implemented interface name in UseInterface.fs, which is Example.DrawingInterfaces.IRepresentable_SVG although as both modules belong to the same namespace the Example prefix may be omitted
second error message points to the need of using instance method in implementation class UseInterface.LineSet, which is achieved by prepending self-identifier __. to the method signature
Finally, notice the usage of your interface in Program.fs that imports namespace, provides module names for definition and implementation respectively, and also explicitly casts implementation LineSet to IRepresentable_SVG.
EDIT: I've added X1Start property to the original LineSet to show how it can be used from interface implementation per question author's request. Now self-id __. is more involved and probably using self. or even this. instead would make more sense.
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 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.
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#).