How to define and use static variables in F# class - f#

Is there a way to have a mutable static variable in F# class that is identical to a static variable in C# class ?

You use static let bindings (note: while necessary some times, it's none too functional):
type StaticMemberTest () =
static let mutable test : string = ""
member this.Test
with get() =
test <- "asdf"
test

Related

Confused about static dictionary in a type, in F#

With this type:
type A =
{
S: string
}
static member private l = Dictionary<string, A>()
static member add s = A.l.[s] <- { S=s }
static member list () = l.Values
if I do:
A.add "hello"
A.add "world"
I'd expect A.list() to return something since the dictionary is static, but it returns an empty list. Why is that?
To clarify what I'm trying to do: I'd like to have the ability to register the objects of type A into a static dictionary that is attached to the type itself as it would make the object repository 'self contained' in the type, in a way.
Your l is not a field, but a property with a getter.
A "property", contrary to appearances, is not a memory cell with some value in it. A "property" is a pair of get+set functions. Just functions, that's all. No memory cell.
So what you made yourself is a property with a getter (without a setter), and all that getter does is create a new Dictionary and return it.
This means, every time you access A.l, you get yourself a new, fresh dictionary. Because l is a function, not a memory cell.
Now, in order to make a memory cell (aka "field"), one would ordinarily use static member val, like so:
static member val private l = Dictionary<string, A>()
Unfortunately, in this particular case this doesn't work, because static fields are not permitted on F# records and unions. They work fine on actual classes, but not on F# types.
So instead what I would recommend is to put those functions in a module rather than making them static methods:
type A = { S: string }
module A =
let private l = Dictionary<string, A>()
let add s = l.[s] <- { S=s }
let list () = l.Values
(and just in general: try to use fewer classes and more modules and functions; they're more idiomatic in F# and lead to fewer problems in general)
Now this works as expected:
> A.add "hello";;
val it : unit = ()
> A.add "world";;
val it : unit = ()
> A.list();;
val it : Dictionary`2.ValueCollection<string,A> =
seq [{ S = "hello" }; { S = "world" }]

Is it possible to use explicit member constraints on static fields?

Using F#, I had the following (simplified), which works fine:
type MyInt =
struct
val Value: int
new v = { Value = v }
end
static member inline name() = "my_int" // relevant line
let inline getName (tp: ^a): string = (^a: (static member name : unit -> string) ())
It seems to me that the statically resolved member signature from the explicit member constraint requires a function. I was wondering if it can also be used with a field instead. I tried a few things:
The following will compile, but won't work and will fail with the error
error FS0001: The type 'MyInt' does not support the operator 'get_name'
type MyInt =
//...
static member inline name = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Removing the () to prevent it from trying to call the gettor is a syntax error. If I change it to actually implement the gettor, it works (but that's essentially the same as the original code).
type MyInt =
// ...
static member inline name with get() = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Is there a way to get, using explicit member constraints or similar means, the compiler to find the static field? Or is this simply a limitation of the syntax of constraints?
Update:
Surprisingly, it does work with instance fields, or as in this case, struct fields: using (^a: (member Value: 'b) ()), which will call the member Value.

When to use static constant and variable in Swift?

There are some posts for how to write code for static constant and static variable in Swift. But it is not clear when to use static constant and static variable rather than constant and variable. Can someone explain?
When you define a static var/let into a class (or struct), that information will be shared among all the instances (or values).
Sharing information
class Animal {
static var nums = 0
init() {
Animal.nums += 1
}
}
let dog = Animal()
Animal.nums // 1
let cat = Animal()
Animal.nums // 2
As you can see here, I created 2 separate instances of Animal but both do share the same static variable nums.
Singleton
Often a static constant is used to adopt the Singleton pattern. In this case we want no more than 1 instance of a class to be allocated.
To do that we save the reference to the shared instance inside a constant and we do hide the initializer.
class Singleton {
static let sharedInstance = Singleton()
private init() { }
func doSomething() { }
}
Now when we need the Singleton instance we write
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
This approach does allow us to use always the same instance, even in different points of the app.
There are some posts for how to write code for static constant and static variable in Swift. But it is not clear when to use static constant and static variable rather than constant and variable. Can someone explain?
When you define a static var/let into a class (or struct), that value will be shared among all the instances (or values).
static variables/class are variables can be accessed without need of creation of any instance/object.
class Human {
static let numberOfEyes = 2 //human have only 2 eyes
static var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable
//other variables and functions
}
//you can access numberOfEyes like below no object of Human is created
print(Human.numberOfEyes)
print(Human.eyeDefect)
//Object of Human
let john = Human()
I think you know difference between constant and variable. In short, constant is that whose value never changes; numberOfEyes in above example and variable is that whose value changes; eyeDefect in above example.
static constant or variables are placed in memory(RAM) separate then the Objects. i.e. numberOfEyes have different memory space allocated than John object, its not inside John.
now, when to use static constants/variables:
When you use singleton design pattern: static let sharedInstance = APIManager()
class APIManager(){
static let sharedInstance = APIManager()
//Your other variables/functions here below
}
//Use it as to get singleton instance of APIManager from anywhere in your application
let instanceOfAPIManager = APIManager.sharedInstance
When you need value of anything that is globally the same without need to make instance of the class under which it is defined like numberOfEyes in human class.
Use of static variables/constants are not much recommended because of memory issues because once it's instantiated/assigned, it remains in memory until your application gets removed from the memory. I have found till now the best place to use static variables/constants is only while making singleton pattern and sometimes pointers for other normal variables and constants don't use static because: memory issue, it will be difficult to run unit testing in your code with static variables/constants. Not recommended to use as like in Human class also. instead use them as just constant or variables and access them by making instance.
class Human {
let numberOfEyes = 2 //human have only 2 eyes
var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable
//other variables and functions
}
//you can access numberOfEyes like below if you need just those values.
print(Human().numberOfEyes)
print(Human().eyeDefect)
Static constants and variables do belong to the class itself, not to a particular instance. A class can also have static methods that can be called without creating an instance of a class.
So when you have a class MyClass with a static var x, you can also access it through MyClass.x directly. x will be shared among all instances of a class
This is more of an important comment:
class Person {
static var name = "Static John" // a property of Person 'type'
var name = "Alex" // a property of Person 'instance'
var nonStaticName = "Peter"
static var staticName = "Sara"
static func statFunc() {
let x = Person.name // Static John
let y = name // Static John or Alex?! Static John!!!!
let r = staticName // Sara
let k = nonStaticName // ERROR: instance member 'nonStaticName' cannot be used on type 'Person'
// The compiler is like: I'm referring to the `nonStaticName` property of which instance?! There is no instance! Sorry can't do!
}
func nonStaticFunc() {
let x = Person.name // Static John
let y = name // Static John or Alex?! Alex!!! Because we're in a instance scope...
let k = nonStaticName // Obviously works
let r = staticName // ERROR: static member 'staticName' cannot be used on instance of type 'Person'. Person.staticName will work
}
}
Interesting observations:
First:
static var name = "Static John" // a property of Person 'type'
var name = "Alex" // a property of Person 'instance'
creates no conflicts.
Second:
You can't ever use instance variables inside static variables. You can use static variables inside instance functions if you refer to it by prefixing it with the type ie do Person.name, whereas
static variables can be accessed inside static functions with or without prefixing the type ie Person.staticName or staticName both work.

F# - public myClass test;

I'm fairly need to this whole F# thing and Functional programming.. I've been looking in all possible documents and found nothing, so therefore I ask you for help for my simple problem. How do I declare:
public myClass test;
in F#?
If you want the declaration to go in the module, do
let test = myClass()
If you want the declaration to go in the class, do
val test: myClass
You'll have to initialize test in the constructor, or to provide a DefaultValue attribute:
[<DefaultValue>]
val mutable test: myClass
Then it will be default-initialized to null.
The final alternative is to have the private field (then you can initialize it inside the class declaration) and provide an accessor:
let test = myClass()
member x.Test = test
or
let mutable test = myClass()
member x.Test with get () = test and set value = test <- value

Using NoRM to access MongoDB from F#

Testing out NoRM https://github.com/atheken/NoRM from F# and trying to find a nice way to use it. Here is the basic C#:
class products
{
public ObjectId _id { get; set; }
public string name { get; set; }
}
using (var c = Mongo.Create("mongodb://127.0.0.1:27017/test"))
{
var col = c.GetCollection<products>();
var res = col.Find();
Console.WriteLine(res.Count().ToString());
}
This works OK but here is how I access it from F#:
type products() =
inherit System.Object()
let mutable id = new ObjectId()
let mutable _name = ""
member x._id with get() = id and set(v) = id <- v
member x.name with get() = _name and set(v) = _name <- v
Is there an easier way to create a class or type to pass to a generic method?
Here is how it is called:
use db = Mongo.Create("mongodb://127.0.0.1:27017/test")
let col = db.GetCollection<products>()
let count = col.Find() |> Seq.length
printfn "%d" count
Have you tried a record type?
type products = {
mutable _id : ObjectId
mutable name : string
}
I don't know if it works, but records are often good when you just need a class that is basically 'a set of fields'.
Just out of curiosity, you can try adding a parameter-less constructor to a record. This is definitely a hack - in fact, it is using a bug in the F# compiler - but it may work:
type Products =
{ mutable _id : ObjectId
mutable name : string }
// Horrible hack: Add member that looks like constructor
member x.``.ctor``() = ()
The member declaration adds a member with a special .NET name that is used for constructors, so .NET thinks it is a constructor. I'd be very careful about using this, but it may work in your scenario, because the member appears as a constructor via Reflection.
If this is the only way to get succinct type declaration that works with libraries like MongoDB, then it will hopefuly motivate the F# team to solve the problem in the future version of the language (e.g. I could easily imagine some special attribute that would force F# compiler to add parameterless constructor).
Here is a pretty light way to define a class close to your C# definition: it has a default constructor but uses public fields instead of getters and setters which might be a problem (I don't know).
type products =
val mutable _id: ObjectId
val mutable name: string
new() = {_id = ObjectId() ; name = ""}
or, if you can use default values for your fields (in this case, all null):
type products() =
[<DefaultValue>] val mutable _id: ObjectId
[<DefaultValue>] val mutable name: string

Resources