Попробуем воспроизвести здесь, как компилятор пытается вывести типы.
let rec Foo(a,b) =
match a () with
| None -> Some(b)
| Some(c) -> Some(Foo(c,b))
«Хорошо, я вижу, что a ()
. a
должна быть функцией от unit
до какого-то типа, я пока не знаю, какого именно. Я назову ее 'a
».
a : unit -> 'a
«Результат a ()
сопоставляется с шаблонами None
/Some
. Таким образом, 'a
должен быть 'b option
, а c
имеет тип 'b
». (Опять же, 'b
обозначает пока неизвестный тип).
a : unit -> 'b option
с : 'b
«Для b
не вызываются никакие функции или методы (кроме Some
, который не сужает тип, и Foo
, тип которого нам пока неизвестен). Я буду обозначать его тип 'c
».
a : unit -> 'b option
b : 'c
c : 'b
«Foo
возвращает Some(b)
в одной из ветвей, поэтому тип возвращаемого значения должен быть 'c option
».
Foo : (unit -> 'b option) * 'c -> 'c option
«Я уже закончил? Нет, мне нужно проверить, что все типы в выражении имеют смысл. Посмотрим, в случае Some(c)
возвращается Some(Foo(c,b))
. Итак, Foo(c,b) : 'c
. Поскольку Foo
возвращает option
, я знаю, что 'c
должно быть 'd option
для некоторых 'd
и b : 'd
. Подождите, у меня уже есть b : 'c
, то есть b : 'd option
. 'd
и 'd option
должны быть одного типа, но это невозможно! В определении должна быть ошибка. Мне нужно сообщить об этом." Так оно и есть.
person
Alexey Romanov
schedule
29.12.2009