Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does F# map implement the interfaces with mutable operations?

I was somewhat surprised when I realised that F#'s map implements both IDictionary<'Key, 'Value> and ICollection<KeyValuePair<'a, 'b>> considering that both supports mutation (add and remove) as part of the contract.

Looking at the implementation of map it simply excepts when you try to cause mutation!

let map = [| (1, "one"); (2, "two") |] |> Map.ofArray
let dict = map :> IDictionary<int, string>
dict.Add(3, "three");;

the above code throws the exception:

System.NotSupportedException: Map values cannot be mutated. at Microsoft.FSharp.Collections.FSharpMap2.System-Collections-Generic-IDictionary2-Add(TKey k, TValue v) at .$FSI_0007.main@() Stopped due to error

which is as expected.

For an immutable collection to be able to expose itself as a mutable one only for it to throw exception when the consumer of that collection tries to cause mutation seems such a dangerous decision.

Am I missing something here?

like image 680
theburningmonk Avatar asked Jun 20 '12 13:06

theburningmonk


People also ask

What does f stand for in math?

more ... A special relationship where each input has a single output. It is often written as "f(x)" where x is the input value. Example: f(x) = x/2 ("f of x equals x divided by 2")

What does f apostrophe mean?

This formula, or new function, is called the derivative of the original function. When we find it we say that we are differentiating the function. The derivative of f(x) is written using an apostrophe after the f. The notation is f´(x) or y´ The notation dy/dx is also commonly used.

What is the formula of f x?

The slope of a linear function is calculated by rearranging the equation to its general form, f(x) = mx + c; where m is the slope. The vertex of a quadratic function is calculated by rearranging the equation to its general form, f(x) = a(x – h)2 + k; where (h, k) is the vertex.


2 Answers

I think the main reason is that .NET does not have any interface that represents immutable (part of an interface of a) dictionary. This means that all .NET APIs have to take IDictionary<K, V> as parameter, even if they only intend to read from the dictionary. So:

  • Implementing IDictionary<'K, 'V> is pretty much the only way to make the F# immutable map usable as a parameter to any .NET libraries that need an object that supports lookup. Sadly, there is no read-only alternative in .NET.

  • Implementing ICollection<KeyValuePair<'K, 'V>> does not make too much sense to me, because there is a read-only alternative IEnumerable<KeyValuePair<'K, 'V>> and immutable map implements this interface too.

    But perhaps there are some .NET libraries that take ICollection<'T> (for efficientcy - i.e. to get Count without enumerating all elements) and use it in a read-only way.

    EDIT: As noted by Daniel in the comment, implementing ICollection is required, because the IDictionary interface inherits from it.

I think the lack of read-only interface is quite unfortunate, but there is probably no way this could be fixed, because it would mean changing the existing .NET collection libraries.

like image 132
Tomas Petricek Avatar answered Jan 02 '23 03:01

Tomas Petricek


IsReadOnly allows for the interface to be read-only even though it provides writable methods.

like image 30
Guvante Avatar answered Jan 02 '23 03:01

Guvante