Сохранение частично примененной функции родовым - PullRequest
7 голосов
/ 29 октября 2010

Можно ли частично применить функцию, такую ​​как bprintf, и предотвратить ее ограничение по первоначальному использованию?

Я бы хотел сделать следующее:

let builder = new System.Text.StringBuilder()
let append = Printf.bprintf builder
append "%i" 10
append "%s" string_value

Ответы [ 3 ]

12 голосов
/ 29 октября 2010

Аспект F #, вызывающий это, называется ограничение значения .Вы можете увидеть, что если вы введете только два объявления let в F # Interactive (чтобы компилятор не определял тип с первого использования):

> let builder = new System.Text.StringBuilder() 
  let append = Printf.bprintf builder ;;

error FS0030: Значениеограничение.Значение 'append' было выведено, чтобы иметь универсальный тип val append: ('_a ->' _b) когда '_a:> Printf.BuilderFormat <' _ b> Либо сделать аргументы для 'append' явными, либо, если вы ненамеревайтесь сделать его универсальным, добавьте аннотацию типа.

Есть отличная статья Дмитрия Ломова из команды F #, которая объясняет это подробно.Как предлагается в статье, одним из решений является добавление явного объявления параметра типа:

let builder = new System.Text.StringBuilder() 
let append<'T> : Printf.BuilderFormat<'T> -> 'T = Printf.bprintf builder 
append "%i" 10 
append "%s" "Hello"

Это будет работать просто отлично.

8 голосов
/ 29 октября 2010

Вы можете добавить явный формат аргумент

let builder = new System.Text.StringBuilder()
let append format = Printf.bprintf builder format
append "%i" 10
append "%s" "1"
6 голосов
/ 29 октября 2010

Вы столкнулись с ограничением значения F #.

Вот хорошее объяснение некоторых обходных путей: Понимание ошибок ограничения значения F #

Вот довольно глубокая статья, объясняющая причины этого: http://blogs.msdn.com/b/mulambda/archive/2010/05/01/value-restriction-in-f.aspx

...