Reputation: 1188
Im using a resource file for strings, and then use also those with placeholders and needs to format the strings.
I have (about) the following code in my project:
let create s = sprintf (Printf.StringFormat<_>(s))
let formatstring = "%s:%d" // this is actually then gotten from the resource strings
let createsomespecificstring s d = create formatstring s d
let resultstring = createsomespecificstring "123" 123
This code works when I use f#3.0. Swapping it to compile it with 3.1, it compiles but gives a runtime error:
Unable to cast object of type 'Final2@235[Microsoft.FSharp.Core.Unit,System.String,System.String,System.String,System.String]' to type 'Microsoft.FSharp.Core.FSharpFunc
2[Microsoft.FSharp.Core.FSharpFunc
2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.PrintfImpl+PrintfEnv3[Microsoft.FSharp.Core.Unit,System.String,System.String]],Microsoft.FSharp.Core.FSharpFunc
2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,System.Object]]]'.
If Im running the above code in repl it doesnt work at all with:
stdin(28,5): error FS0030: Value restriction. The value 'resultstring' has been inferred to have generic type val resultstring : '_a
Either define 'resultstring' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
The above code somewhat defeats the purpose of strong typing again, but its kind of nice when one has resource strings.
Am I doing something wrong (besides mentioned above)?
Any ideas on how to do it better and even make it work (especially in 3.1)?
Edit: After first answer (which works in that specific case) the number of formating options/arguments are "random" length:
let formatstring = "%s:%d:%d"
let createsomespecificstring s d d' = create formatstring s d d'
let resultstring = createsomespecificstring "123" 123 345
Then it does not work again.
Upvotes: 3
Views: 434
Reputation: 1188
Type annotation as @kvp hints at is the "correct" answer.
let createsomespecificstring s d d' : string = create formatstring s d d'
That does it in fsi, and in f# 3.1 when compiled on the tests I have done.
Upvotes: 1
Reputation: 25516
Here is a solution that works at least in fsi:
let create s = sprintf (Printf.StringFormat<_ -> _ -> string >(s))
let formatstring = "%s:%d" // this is actually then gotten from the resource strings
let createsomespecificstring s d = create formatstring s d
let resultstring = createsomespecificstring "123" 123
All that I needed was to add some extra dummy parameters and to enforce the return type of the sprintf to be a string.
Upvotes: 0