Something quite odd is happening with y types and I quite dont understand if this is justified or not. I would tend to think not.
This code works fine :
type DictionarySingleton private () =
static let mutable instance = Dictionary<string*obj, obj>()
static member Instance = instance
let memoize (f:'a -> 'b) =
fun (x:'a) ->
let key = f.ToString(), (x :> obj)
if (DictionarySingleton.Instance).ContainsKey(key)
then let r = (DictionarySingleton.Instance).[key]
r :?> 'b
else
let res = f x
(DictionarySingleton.Instance).[key] <- (res :> obj)
res
And this ones complains
type DictionarySingleton private () =
static let mutable instance = Dictionary<string*obj, _>()
static member Instance = instance
let memoize (f:'a -> 'b) =
fun (x:'a) ->
let key = f.ToString(), (x :> obj)
if (DictionarySingleton.Instance).ContainsKey(key)
then let r = (DictionarySingleton.Instance).[key]
r :?> 'b
else
let res = f x
(DictionarySingleton.Instance).[key] <- (res :> obj)
res
The difference is only the underscore in the dictionary definition. The infered types are the same, but the dynamic cast from r to type 'b exhibits an error.
'this runtime coercition ... runtime type tests are not allowed on some types, etc..'
Am I missing something or is it a rough edge ?
If you compile in two steps, first the Type DictionarySingleton
, then the Function memoize
it works.
Looks like the compiler tries first to figure out the type of the underscore (which may be a generic type) and before deciding it's obj
it also tries to infer the type of r. So at that point it is still not unified with obj
, that's why it fails if you compile in one shot.