1

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 ?

nicolas
  • 9,549
  • 3
  • 39
  • 83

1 Answers1

1

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.

Gus
  • 25,839
  • 2
  • 51
  • 76
  • it might be worth submitting this to the fine fsbugs folks. thanks for checking. – nicolas Jun 24 '12 at 19:48
  • excellent articles on type classes btw ... static and inline is not straight forward.. – nicolas Jun 24 '12 at 19:51
  • Thanks @nicolas ! It might, but I'm not sure if it's a bug or a feature. I mean, sometimes type inference looks ahead to infer the type, to solve for example value restrictions, which I think is more a feature. I don't know if they can enhance the inference for these particular cases. – Gus Jun 24 '12 at 19:55
  • may be look ahead could be carried over for r as well .. ? I'll let them know, up to them to take action or not. btw I sent an enhancement suggestion related to a script you wrote originally. cf https://github.com/nrolland/AlgoInFSharpMinor/blob/master/Algo2/Algo2/Script1.fsx – nicolas Jun 24 '12 at 20:08
  • Did I wrote that? Maybe it was another Gustavo ;) Anyway I can tell you I reported some bugs to fsbugs and I got always some feedback from them, I think it worth. – Gus Jun 24 '12 at 20:21
  • I think you wrote the 1st version to gather all the dependencies for a project into a file to be loaded in fsx. I extended it for solution, across projects. http://stackoverflow.com/questions/9998144/fsx-script-referencing-a-dll-referencing-many-dll – nicolas Jun 24 '12 at 20:26
  • I see now, it's Gustavo Guerra, I'm Gustavo Leon, thanks anyway :) – Gus Jun 24 '12 at 20:42
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12972/discussion-between-gustavo-and-nicolas) – Gus Jun 24 '12 at 20:45
  • As an aside - be careful with Dictionary if your code is going to be called in a threaded/parallel situation - you may get 'Key already exists' errors. Consider ConcurrentDictionary in that case: http://msdn.microsoft.com/en-us/library/dd287191.aspx. For example, Luca Bolgnese's code to replicate the Excel 'YearFrac' function fails for exactly this reason. – Kit Jun 25 '12 at 14:05