Helge Rene Urholm
Helge Rene Urholm

Reputation: 1188

F# error with sprintf and format

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.FSharpFunc2[Microsoft.FSharp.Core.FSharpFunc2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.PrintfImpl+PrintfEnv3[Microsoft.FSharp.Core.Unit,System.String,System.String]],Microsoft.FSharp.Core.FSharpFunc2[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

Answers (2)

Helge Rene Urholm
Helge Rene Urholm

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

John Palmer
John Palmer

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

Related Questions