F# ошибка с sprintf и форматом

Я использую файл ресурсов для строк, а затем использую также файлы с заполнителями и должен форматировать строки.

У меня есть (примерно) следующий код в моем проекте:

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

Этот код работает, когда я использую F#3.0. Поменяв его на 3.1, он компилируется, но выдает ошибку времени выполнения:

Невозможно привести объект типа 'Final2@235[Microsoft.FSharp.Core.Unit,System.String,System.String,System.String,System.String]' для ввода '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]]]".

Если я запускаю приведенный выше код в repl, он вообще не работает с:

стандартный ввод (28,5): ошибка FS0030: ограничение значения. Значение 'resultstring' было выведено, чтобы иметь универсальный тип val resulttring: '_a
Либо определите "результирующую строку" как простой термин данных, сделайте его функцией с явными аргументами или, если вы не собираетесь использовать его как универсальный, добавьте аннотацию типа.

Приведенный выше код в некоторой степени лишает смысла строгую типизацию, но это приятно, когда есть строки ресурсов.

Я делаю что-то не так (кроме упомянутого выше)?

Любые идеи о том, как сделать это лучше и даже заставить его работать (особенно в 3.1)?

Редактировать: после первого ответа (который работает в этом конкретном случае) число форматирующих опций / аргументов имеет "случайную" длину:

let formatstring = "%s:%d:%d"
let createsomespecificstring s d d'  = create formatstring s d d'
let resultstring = createsomespecificstring "123" 123 345

Тогда это не работает снова.

2 ответа

Решение

Тип аннотации, как подсказывает @kvp, является "правильным" ответом.

let createsomespecificstring s d d' : string = create formatstring s d d'

Это происходит в fsi и в F# 3.1 при компиляции на тестах, которые я провел.

Вот решение, которое работает по крайней мере в ФСИ:

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

Все, что мне было нужно, это добавить несколько дополнительных фиктивных параметров и заставить возвращаемый тип sprintf быть строкой.

Другие вопросы по тегам