Equality inference in F# + records with mutable fields - f#

The common equality/comparison members design guideline is to not implement structural equality on mutable reference types, but take a look at F# record types with mutable fields:
type Value = { mutable value: int }
let mutableRecord = { value = 1 }
let xs = Map.ofList [ mutableRecord, "abc"
{ value = 2 }, "def" ]
let abc = Map.find { value=1 } xs
mutableRecord.value <- 3
let abc = Map.find { value=3 } xs // KeyNotFoundException!
The Map is sorted internally, but mutable record fields allows me to change ordering while record instance is already inside map and this is very bad.
I think F# should infer [<NoEquality>] and [<NoComparison>] modes for F# record types that declares mutable fields, isn't it?

That's not an unreasonable stance.
There might be some clever ways to leverage this feature usefully, though I haven't thought about it deeply enough. This is basically the same thing as when you put a mutable type in a Dictionary, and you get what you deserve. (Languages can't prevent every misuse, which is why we have design guidelines and programmer judgment to fill in the gaps :) )
Anyway, there's no changing it now.

Related

Types vs. Modules in F#

The answer on Confused about static dictionary in a type, in F# finished with one advice: 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
Which is a great point, but my 30 years of OO just don't want to give up classes just yet (although I was fighting against C++ like crazy when we moved away from C...)
so let's take a practical real world object:
type Currency =
{
Ticker: string
Symbol: char
}
and MarginBracket =
{
MinSize: decimal
MaxSize: decimal
Leverage: int
InitialMargin: decimal
MaintenanceMargin: decimal
}
and Instrument =
{
Ticker: string
QuantityTickSize: int
PriceTickSize: int
BaseCurrency: Currency
QuoteCurrency: Currency
MinQuantity: decimal
MaxQuantity: decimal
MaxPriceMultiplier: decimal
MinPriceMultiplier: decimal
MarginBrackets: MarginBracket array
}
// formatting
static member private formatValueNoSign (precision: int) (value: decimal) =
let zeros = String.replicate precision "0"
String.Format($"{{0:#.%s{zeros}}}", value)
static member private formatValueSign (precision: int) (value: decimal) =
let zeros = String.replicate precision "0"
String.Format($"{{0:+#.%s{zeros};-#.%s{zeros}; 0.%s{zeros}}}", value)
member this.BaseSymbol = this.BaseCurrency.Symbol
member this.QuoteSymbol = this.QuoteCurrency.Symbol
member this.QuantityToString (quantity) = $"{this.BaseSymbol}{Instrument.formatValueSign this.QuantityTickSize quantity}"
member this.PriceToString (price) = $"{this.QuoteSymbol}{Instrument.formatValueNoSign this.PriceTickSize price}"
member this.SignedPriceToString (price) = $"{this.QuoteSymbol}{Instrument.formatValueSign this.PriceTickSize price}"
member this.RoundQuantity (quantity: decimal) = Math.Round (quantity, this.QuantityTickSize)
member this.RoundPrice (price : decimal) = Math.Round (price, this.PriceTickSize)
// price deviation allowed from instrument price
member this.LowAllowedPriceDeviation (basePrice: decimal) = this.MinPriceMultiplier * basePrice
member this.HighAllowedPriceDeviation (basePrice: decimal) = this.MaxPriceMultiplier * basePrice
module Instrument =
let private allInstruments = Dictionary<string, Instrument>()
let list () = allInstruments.Values
let register (instrument) = allInstruments.[instrument.Ticker] <- instrument
let exists (ticker: string) = allInstruments.ContainsKey (ticker.ToUpper())
let find (ticker: string) = allInstruments.[ticker.ToUpper()]
In this example, there is an Instrument object with its data and a few helper members and a module which acts as a repository when it's time to find an object by name (a trading ticker in this case, so they're known and formatted, it's not a random string)
I could move the helping member to the module, for example:
member this.LowAllowedPriceDeviation (basePrice: decimal) = this.MinPriceMultiplier * basePrice
could become:
let lowAllowedPriceDeviation basePrice instrument = instrument.MinPriceMultiplier * basePrice
So the object would become simpler and could eventually be turned into a simple storage type without any augmentations.
But I am wondering what are the practical benefits (let's just consider readability, maintainability, etc)?
Also, I don't see how this could be re-structured to not be a class, short of having an 'internal' class in the module and doing all operations through that, but that would just be shifting it.
Your intuition about turning LowAllowedPriceDeviation to a module is correct: it could become a function with the this parameter moved to the end. That is an accepted pattern.
Same goes for all other methods on the Instrument type. And the two private static methods could be come private functions in the module. The exact same approach.
The question "how this could be re-structured to not be a class" confuses me a bit, because this is not actually a class. Instrument is a record, not a class. The fact that you gave it some instance and static methods doesn't make it a class.
And finally (though, technically, this part is opinion-based), regarding "what are the practical benefits" - the answer is "composability". Functions can compose in the way that methods can't.
For example, say you wanted a way to print multiple instruments:
let printAll toString = List.iter (printfn "%s" << toString)
See how it's parametrized with a toString function? That's because I'd like to use it for printing instruments in different ways. For example, I might print their prices:
printAll priceToString (list())
But if PriceToString is a method, I'd have to introduce an anonymous function:
printAll (fun i -> i.PriceToString) (list())
This looks just a little bit more involved than using a function, but in practice it gets very complicated fast. A bigger problem, however, is that this wouldn't even compile because type inference doesn't work on properties (because it can't). In order to get it to compile, you have to add a type annotation, making it even uglier:
printAll (fun (i: Instrument) -> i.PriceToString) (list())
That's just one example of function composability, there are many others. But I'd rather not write a whole blog post on this subject, it's already much longer than I'd like.

IgnoreMissingMember setting doesn't seem to work with FSharpLu.Json deserializer

This is a following to: deserialization issue, with json.net, in F#.
I am deserializing some JSON that has an extra, unbound property using FSharpLu.Json. Here is the code:
open System
open Newtonsoft.Json
open Microsoft.FSharpLu.Json
type r =
{
a: int
}
let a =
"{\"a\":3, \"b\":5}"
Compact.TupleAsArraySettings.settings.MissingMemberHandling <- MissingMemberHandling.Ignore
Compact.deserialize<r> a // doesn't work
Despite setting MissingMemberHandling.Ignore it returns a json.net error:
Could not find member 'b' on object of type 'r'. Path 'b', line 1, position 13.
Is there a way to make this work, or is it an issue with FSharpLu.Json?
Here is the fiddle: https://dotnetfiddle.net/OsVv1M
as a side note, there is another deserializer in FSharpLu.Json and I can get that code to work with it:
FSharpLu.Json.Default.Internal.DefaultSettings.settings.MissingMemberHandling <- MissingMemberHandling.Ignore
Default.deserialize<r> a
will work, but that deserializer doesn't handle discriminated unions... so I need to get the compact one to work.
When looking into the source of FSharpLu.Json, I found this:
/// Compact serialization where tuples are serialized as heterogeneous arrays
type TupleAsArraySettings =
static member formatting = Formatting.Indented
static member settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
// MissingMemberHandling is not technically needed for
// compact serialization but it avoids certain ambiguities
// that guarantee that deserialization coincides with the
// default Json.Net deserialization.
// (where 'coincides' means 'if the deserialization succeeds they both return the same object')
// This allows us to easily define the BackwardCompatible
// serializer (that handles both Compact and Default Json format) by reusing
// the Compact deserializer.
MissingMemberHandling = MissingMemberHandling.Error,
Converters = [| CompactUnionJsonConverter(true, true) |]
)
so they are explicitly setting the MissingMemberHandling to Error; maybe the solution is to instantiate the deserializer, change the setting and then use it.
The serializer setting you are trying to mutate, Compact.TupleAsArraySettings.settings, is a static member, as is shown in the code:
type TupleAsArraySettings =
static member formatting = Formatting.Indented
static member settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
// MissingMemberHandling is not technically needed for
// compact serialization but it avoids certain ambiguities
// that guarantee that deserialization coincides with the
// default Json.Net deserialization.
// (where 'coincides' means 'if the deserialization succeeds they both return the same object')
// This allows us to easily define the BackwardCompatible
// serializer (that handles both Compact and Default Json format) by reusing
// the Compact deserializer.
MissingMemberHandling = MissingMemberHandling.Error,
Converters = [| CompactUnionJsonConverter(true, true) |]
)
Since a member is actually a member function (i.e. a method) as explained F# for fun and profit: Attaching functions to types, settings is actually (in c# terminology) a static property returning a new instance of JsonSerializerSettings each time it is invoked. To test this, we can do:
printfn "%b" (Object.ReferenceEquals(Compact.TupleAsArraySettings.settings, Compact.TupleAsArraySettings.settings)) // prints "false"
Which prints "false". Thus mutating the returned value has no effect on the behavior of Compact. A static field in the c# sense would be defined by a static let statement; if settings returned such a field, mutating its contents would have had an effect.
In any event modifying the value of Compact.TupleAsArraySettings.settings.MissingMemberHandling seems unwise as doing so would modify the behavior of of Compact.deserialize throughout your entire AppDomain in a way that might break backwards compatibility with Json.NET native serialization. As explained in the code comments above, the setting is required to make BackwardCompatible.deserialize work. But why might that be? Since Json.NET's native format for option and discriminated unions looks like:
{
"a": {
"Case": "Some",
"Fields": [
3
]
}
}
We can guess that MissingMemberHandling is used to trap situations where "Case" and "Fields" are found or not, and switch from one algorithm to the other.
If you are certain you do not need to deserialize f# types in Json.NET format, it seems you should be able to use CompactUnionJsonConverter directly as follows:
let settings = JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
Converters = [| CompactUnionJsonConverter(true, true) |]
)
let c = JsonConvert.DeserializeObject<r>(a, settings)
let json2 = JsonConvert.SerializeObject(c, Formatting.Indented, settings)
Demo fiddle here.

Explanation and idiomatic solution(s) for assignments to arrays in classes in F#

I've been trying out F# a bit recently, but I've almost exclusively used records and immutability. Now I'm trying mutable classes, however, and it's giving me some issues.
The biggest one so far is that it seems I can't assign to an element of an array that is a member of a class. For example, the following works as expected, replacing the 0th element with a 9:
let array = [| 0..5 |]
array.[0] <- 9
printfn "%A" array
However, this does not work as I would expect:
type MyClass () =
member this.Array = [| 0..5 |]
let myClass = MyClass()
myClass.Array.[0] <- 9
printfn "%A" myClass.Array
The assignment seems to do nothing, but the compiler does not complain with even a warning. I assume there is something that prevents assignments to members of classes, including their submembers and elements, but I can't find any documentation or outside explanations of it.
Could someone help me understand what's going on here and give an example or two of how this is typically done?
MyClass.Array, the way you declared it, is a readonly property. You gave it a get accessor, and the body of that accessor consists of creating an array and returning it.
Spot the problem yet? It's a new array every time you call MyClass.Array. The first array does get mutated just fine, but then you just throw it away and request a new array from the class.
If you want to "store" an array "inside" the class, you need to give it a name, and then make your property accessor refer to that name. That way, the property accessor will return the same array every time:
type MyClass() =
let theArray = [|0..5|]
member this.Array = theArray
(incidentally, this very gotcha is one of the reasons to avoid mutable data)
This is probably because the declaration you have defines this.Array as a read-only property. As mentioned in another answer, the code you have returns a new array for each call.
An auto property works and is a little more concise:
type MyClass () =
member val Array = [| 0..5 |] with get,set
let myClass = MyClass()
myClass.Array.[0] <- 9
printfn "%A" myClass.Array // [|9; 1; 2; 3; 4; 5|]

F# cons operator and list in class

So here is my question. I have a python project that is very functionally oriented...but which fundamentally runs with classes...so F# seemed the ideal language for a compiled version of my code (I'd like to black box my source code...the python code is just sitting there in files. Not cool).
In my python class, I have a generic container--a python list. This container will contain arrays of a uniform length in a given implementation...
Here is my problem: I need to add arrays to the list after initialization.
What is the proper way to add arrays to the list in the class?
Here is what I have...but it seems like it will be slow, since it throws out the old list with a new copy (right??):
type myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value::_training
However, this fails (even after the edits suggested below) because the compiler claims that the set function is an obj with set rather than an obj list with set, even though it acknowledges that _training is a mutable obj list on the left side of the <- in the set function...I'm stumped)
What is the proper "F#" way to do this?
The 'proper' F# way to do it is to not have that myclass class at all. A class with a single getter and setter provides no value over an immutable list.
That said, the above code doesn't compile for a number of reasons:
A type is defined with =, not :.
_training isn't bound by with a let expression.
If you want to mutate the _training value, you must declare it let mutable
Even so, the return value of get is obj list, but the input value of set (which is the symbol value) is obj, because of the use of the cons operator (::). As the compiler says, the type of get and set must be the same.
You can make it compile by addressing all these concerns:
type Myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value
but it would accomplish nothing. If you need a list, then pass a list. It's not that we don't believe in encapsulation in F#, but properties aren't equivalent to encapsulation anyway...
BTW, it'd be idiomatic to name types using Pascal Case, so MyClass instead of myclass. The leading underscore isn't used much either, so it should be training instead of _training.
The problem is that a property has a type,
and the getter and setter must be compatible with that type.
If I run your code interactively, the compiler helpfully tells me exactly that!
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(value) = _training <- value::_training
// error FS3172: A property's getter and setter must have the same type.
// Property 'training' has getter of type 'obj list'
// but setter of type 'obj'.
The answer is simply to have a different method that prepends an element
to the list:
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(newTraining) = _training <- newTraining
member this.prepend(element) =
_training <- (element::_training)
member this.prependList(list) =
_training <- (list # _training)
// test
let myList = myclass()
myList.prepend(1)
myList.prepend(2)
myList.training // output => [2; 1]
myList.prependList([3;4])
myList.training // output => [3; 4; 2; 1]
It's not a nice implementation from a functional point of view,
but it does answer your question.
Note that if you do want a pure functional implementation,
you don't need a class at all.
// test
let myList = []
let myList2 = 1::myList
let myList3 = 2::myList2
// myList3 => [2; 1]
let myList4 = [3;4] # myList3
// myList4 => [3; 4; 2; 1]
Now, how to work with immutable state in a nice way -- that's a whole
other question! :)

Why to use tuples when we can use array to return multiple values in swift

Today I was just going through some basic swift concepts and was working with some examples to understand those concepts. Right now I have completed studying tuples.
I have got one doubt i.e, what is the need of using tuples ? Ya I did some digging on this here is what I got :
We can be able to return multiple values from a function. Ok but we can also do this by returning an array.
Array ok but we can return an multiple values of different types. Ok cool but this can also be done by array of AnyObject like this :
func calculateStatistics (scores:[Int])->[AnyObject]
{
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores
{
if score > max{
max = score
}
else if score < min{
min = score
}
sum += score
}
return [min,max,"Hello"]
}
let statistics = calculateStatistics([25,39,78,66,74,80])
var min = statistics[0]
var max = statistics[1]
var msg = statistics[2] // Contains hello
We can name the objects present in the tuples. Ok but I can use a dictionary of AnyObject.
I am not saying that Why to use tuples when we have got this . But there should be something only tuple can be able to do or its easy to do it only with tuples. Moreover the people who created swift wouldn't have involved tuples in swift if there wasn't a good reason. So there should have been some good reason for them to involve it.
So guys please let me know if there's any specific cases where tuples are the best bet.
Thanks in advance.
Tuples are anonymous structs that can be used in many ways, and one of them is to make returning multiple values from a function much easier.
The advantages of using a tuple instead of an array are:
multiple types can be stored in a tuple, whereas in an array you are restricted to one type only (unless you use [AnyObject])
fixed number of values: you cannot pass less or more parameters than expected, whereas in an array you can put any number of arguments
strongly typed: if parameters of different types are passed in the wrong positions, the compiler will detect that, whereas using an array that won't happen
refactoring: if the number of parameters, or their type, change, the compiler will produce a relevant compilation error, whereas with arrays that will pass unnoticed
named: it's possible to associate a name with each parameter
assignment is easier and more flexible - for example, the return value can be assigned to a tuple:
let tuple = functionReturningTuple()
or all parameters can be automatically extracted and assigned to variables
let (param1, param2, param3) = functionReturningTuple()
and it's possible to ignore some values
let (param1, _, _) = functionReturningTuple()
similarity with function parameters: when a function is called, the parameters you pass are actually a tuple. Example:
// SWIFT 2
func doSomething(number: Int, text: String) {
println("\(number): \(text)")
}
doSomething(1, "one")
// SWIFT 3
func doSomething(number: Int, text: String) {
print("\(number): \(text)")
}
doSomething(number: 1, text: "one")
(Deprecated in Swift 2) The function can also be invoked as:
let params = (1, "one")
doSomething(params)
This list is probably not exhaustive, but I think there's enough to make you favor tuples to arrays for returning multiple values
For example, consider this simple example:
enum MyType {
case A, B, C
}
func foo() -> (MyType, Int, String) {
// ...
return (.B, 42, "bar")
}
let (type, amount, desc) = foo()
Using Array, to get the same result, you have to do this:
func foo() -> [Any] {
// ...
return [MyType.B, 42, "bar"]
}
let result = foo()
let type = result[0] as MyType, amount = result[1] as Int, desc = result[2] as String
Tuple is much simpler and safer, isn't it?
Tuple is a datastructure which is lighter weight than heterogeneous Array. Though they're very similar, in accessing the elements by index, the advantage is tuples can be constructed very easily in Swift. And the intention to introduce/interpolate this(Tuple) data structure is Multiple return types. Returning multiple data from the 'callee' with minimal effort, that's the advantage of having Tuples. Hope this helps!
A tuple is ideally used to return multiple named data from a function for temporary use. If the scope of the tuple is persistent across a program you might want to model that data structure as a class or struct.

Resources