Почему здесь обобщается значение с явной аннотацией типа?

#f# #value-restriction

#f# #ограничение по значению

Вопрос:

Я получаю ошибку VR при привязке let к области видимости модуля, в которой говорится, что один из его параметров является общим, но я не знаю, почему этот параметр является общим в первую очередь. Это код:

 let private asJsonResponse (responseSource: _ Task) =
    fun (next: HttpFunc) (ctx: HttpContext) ->
        task {
            let! consumption = responseSource
            return! json consumption next ctx
        }

let getVal = someFuncThatReturnsTaskOfMyType() |> asJsonResponse
 

Ошибка находится в последней строке:

ошибка FS0030: ограничение значения. Предполагается, что значение getVal имеет общий тип val getVal: (HttpFunc -> '_a -> Task<HttpContext option>) , если '_a :> HttpContext либо сделать аргументы getVal явными, либо, если вы не хотите, чтобы оно было общим, добавить аннотацию типа.

Я понимаю, что оно по существу обобщается ctx: HttpContext на что-то, к чему можно привести HttpContext . Почему это происходит? И почему только для этого параметра, а не next: HttpFunc ?

HttpContext это класс и HttpFunc это тип функции, в этом проблема?

Комментарии:

1. Вы уверены, что это именно тот код, с которым вы работаете? Может быть, вы забыли перекомпилировать модуль после внесения изменений?

2. @FyodorSoikin Я выполнил полную перестройку перед публикацией здесь, чтобы убедиться, что код скопирован из моего исходного файла (за исключением некоторых изменений имени).

3. Попробуйте добавить аннотации типов повсюду и посмотрите, что произойдет. В этом случае я предполагаю asJsonResponse , что это должна делать аннотация типа on .

Ответ №1:

Он компилируется, если вы добавляете аннотации типов:

 let getVal: HttpFunc -> HttpContext -> Task<HttpContext option> =
    someFuncThatReturnsTaskOfMyType() |> asJsonResponse
 

Или добавьте явный параметр:

 let getVal f = asJsonResponse (someFuncThatReturnsTaskOfMyType()) f
 

Простой ответ заключается в том, что механизм вывода типов компилятора F # не идеален. Вы можете прочитать об этом здесь :

Компилятор F # пытается угадать наиболее обобщенный тип, который подходит, но в некоторых случаях компилятор чувствует, что код неоднозначен, и, хотя кажется, что он угадывает тип правильно, ему нужно, чтобы вы были более конкретными

и для получения более подробной информации, вот документация:

Автоматическое обобщение MSDN в F # имеет несколько примеров этого

Обычно ошибка ограничения значения возникает либо когда вы хотите, чтобы конструкция была универсальной, но у компилятора недостаточно информации для ее обобщения, либо когда вы непреднамеренно опускаете достаточную информацию о типе в негенеральной конструкции.