1

В Haskell вы можете сделать следующее:Взаимно рекурсивные типы в OCaml

Prelude> data Foo = Foo Bar; data Bar = Bar Foo 

Как вы можете сделать то же самое в OCaml? Я пробовал:

    ___ 
# type foo = Foo of bar;; type bar = Bar of foo;; 
Error: Unbound type constructor bar 

Возможно ли даже определить взаимно-рекурсивные типы данных в OCaml? Если нет, то почему?

Сравнение определений данных, позволяющих выражениям: взаимно-рекурсивные типы данных соответствуют использованию let rec (или более подходящим образом type rec за отсутствием лучшей фразы). Каковы преимущества возможности определения взаимно-рекурсивных типов данных? Мой пример foobar тривиален. Можете ли вы придумать какие-либо нетривиальные виды использования взаимно-рекурсивных типов данных?

ответ

3

ivg ответил на ваш вопрос, но вот нетривиальным взаимно рекурсивный тип.

module Stream = struct 

    type 'a t = unit -> 'a node 
    and 'a node = Nil 
       | Cons of 'a * 'a t 

end 

Это подлинный тип позвоночника-ленивым потоков. Тем не менее, вы можете построить его без взаимно рекурсивных типов

type 'a t = Stream of (unit -> ('a * 'a t) option) 

Навскидку моя мысль в том, что вы всегда можете уменьшить семейство взаимно рекурсивных типов в один, если вам нравится (хотя, возможно, не в OCaml-кодирования I думая о том, что будет делать нетривиальное использование индексов зависимого типа), но это, безусловно, может быть более ясным.

+1

. Фактически, ваше определение второго типа не работает, он скажет, что определение типа является циклическим. Правильным способом будет «type» a t = Stream of (unit -> ('a *' a t) option) ' – ivg

+0

О, кричит! Да, не проверял его в интерпретаторе. Исправлено сейчас, спасибо. –

7

Использование and

type foo = Foo of bar 
and bar = Bar of foo 
+1

Явная взаимная рекурсия. Мне это больше, чем синтаксис Haskell. Явный всегда лучше, чем неявный. –

+2

Это на самом деле досадно немного меньше, чем полностью явное. То, что было бы максимально явным, было бы 'type rec foo = Foo of bar и bar = Bar of foo'. Вы сталкиваетесь с (небольшими) проблемами, когда, например, есть эмбиентный тип 't', и вы хотите сделать новый тип' t' в подмодуле, который псевдонимы окружающего 't', но' type t module X = struct type t = t end' - ошибка, потому что предполагается, что вы хотите построить бесконечный тип 'type x = x'. –

+0

есть интересный несколько лет [обсуждение] (http://caml.inria.fr/mantis/view.php?id=6623) по этой теме, в результате чего появляется новое ключевое слово 'nonrec'. В 4.03 мы будем иметь 'type nonrec t' и даже (я не уверен, закончилось ли это в последнем патче)' type rec t'. – ivg