Я пытаюсь построить последовательность рекурсивных модулей в ocaml. Вот минимально простой пример:Связывание типа OCaml в рекурсивных модулях
module rec Foo : sig
type t =
| A of int
| B of Foo.t
end = struct
type t =
| A of int
| B of Foo.t
end
module rec Bar : sig
open Foo
type map_t = int -> Foo.t
type t = { foo : map_t }
val bar_of_foo : Foo.t -> t
end = struct
open Foo
let rec bar_of_foo f = match f with
| A a -> let ff (_:int) = a in
{ Bar.foo = ff }
| B b -> { foo = bar_of_foo b.foo }
end
Компиляция проваливается в функции bar_of_foo
, в матче А с Error: unbound type constructor f
.
Я не понимаю, почему это происходит - поле foo
определяется как имеющий тип map_t = int -> Foo.t
и f
имеет подпись int -> Foo.t
.
Я также попытался просто ссылаясь на поля записи foo
в foo
, а не Bar.foo
(в случае соответствия для B
- что дает мне Errror: unbound record field foo
ошибку).
Любые указания или рекомендации с благодарностью получены.
Стив
(1) Внутренний 'f' (внешний' f' является параметром для 'bar_of_foo') имеет подпись' Int -> int', так как он использует 'а: Int 'как возвращаемое значение. Я думаю, что это хорошая идея, чтобы удалить столкновение имен. (2) Я не вижу рекурсивных зависимостей между 'Foo' и' Bar'. Я просто вижу, что 'Bar' использует' Foo', но не наоборот. –
Спасибо Антон. Название столкновения удалено в сообщении. –
ОК, поэтому я не понимаю, как печатает текст в 'bar_of_foo'. Первая строка: '| A a -> let ff (_: int) = a в {Bar.foo = ff} ' начинается с сопоставления с типом' A' (= 'Foo.A'). И тип 'Foo.A' -' int'. Поэтому я понимаю, почему подпись 'ff' является' int -> int'. Но A является одним из вариантов 'Foo.t', поэтому почему' bar_of_foo' не имеет подписи 'Foo.t -> int'? –