There is nothing wrong with your memoize function however the F# (and .Net as a whole) type system does not allow you to do what you seem to want to do.
Dictionary<'T, 'U> is generic however for each instance of a Dictionary, ‘T and ‘U need to be concrete types. You cannot have a single Dictionary containing a wide variety of different types as keys even if they all resolve to string as values.
The way around this is to make all the keys some common type using an Interface for when the keys are in an unbounded set (
obj can even be used as the supertype of everything) or Discriminated Unions when the keys are in a known set.
The following code is an example of using
obj as the key.
module Sample = open System.Collections.Generic let memoize f = let cache = Dictionary<_, _>() fun x -> if cache.ContainsKey(x) then cache.[x] else let res = f x cache.[x] <- res res let memoizedFunc: (obj -> string) = memoize (fun x -> printfn "Not in cache, getting string of %s" (string x) string x) memoizedFunc 1 memoizedFunc "hello" memoizedFunc 1
Your second question I am no expert on. In general type annotations are only to aid the author and do not affect semantics. In code that does not compile they can change the error messages displayed sometimes. Annotations can make a funciton less generic using the
when 'a: expr syntax than may be otherwise inferred by the compiler. These annotations are also required when the compiler detects constraints in generic code.
CLICK HERE to find out more related problems solutions.