The code below shows a situation where some record is being processed by 2 functions of the same signature (RwA -> RwA). Yet, depending on the implementation of that changer function, the data passed to it might be changed or not.
In a larger project, such things can be costly. Maybe during maintenance or during optimization, the implementation of a function is changed or more changer functions are being added, the program still looks the same, yet suddenly behaves in unexpected ways.
So the question is: Is there any way to render the code in this sample such, that it is obvious (and compiler checked), that a function of type RwAChanger may or may not change the data it is passed as a parameter?
Please do not reply "don't use arrays", as this could be large amounts of data, such as vertices of a 3D mesh or alike, where performance would be an issue. Also, I am sure it is possible to find other examples, which do not involve arrays which produce the same type of problems.
// A record with arrays...
type RwA =
{
A : int array
I : int array
}
let x = [| for i in 0..10 -> i |]
let init a =
{ A = a; I = Array.map (fun v -> -v ) a }
// This function creates a new array as member A in RwA
let change (o : RwA) : RwA =
{ o with A = Array.map (fun v -> v + 42) o.A }
// This function modifies the value of the array in member A of an RwA instance.
let change2 (o: RwA) : RwA =
o.A.[0] <- 666
o
let dump (o : RwA) =
printfn "{ A = %A; I = %A; }" o.A o.I
o
let dumpA (a : int array) : int array =
printfn "x = %A" x
a
// Is there a way to express a contract about immutability?
type RwAChanger = RwA -> RwA
let transmogrify (changer : RwAChanger) a =
a
|> dumpA
|> init
|> dump
|> changer
|> dump
|> ignore
let test() =
transmogrify change x
dumpA x |> ignore
transmogrify change2 x
dumpA x |> ignore
do test()
I don't think there's a way to tell the compiler that an existing mutable type should be made immutable, nor use Code Contracts as @mydogisbox mentions in a comment.
You may however be able to use an ImmutableArray<T> from the Microsoft.Bcl.Immutable package in your RwA record. The performance difference for array access should be minimal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With