Я бы создал объявление типа записи, например
type 'a cx = { foo : string, handler : 'a cx -> 'a cx }
но этот код не компилируется.
Я также пробовал «взаимно рекурсивные объявления синонимов типов», вроде
type 'a cx = { foo : string, handler : 'a hnd }
and 'a hnd = 'a cx -> 'a cx;
безуспешно.
В Haskell это будет
data Cx a = MkCx { foo :: String, handler :: Cx a -> Cx a }
Как я могу добиться этого в SML?
Это возможно с mtually рекурсивными типами данных
datatype 'a cx = MkCx of string * ('a hnd)
and 'a hnd = MkHnd of 'a cx -> 'a cx;
но это уродливо, и нет хорошего синтаксиса записи с неупорядоченным доступом.
В итоге я упаковал отдельные типы в один модуль, т.е.
type 'a cx = { foo : string };
type 'a hnd = 'a cx -> 'a cx
signature CX = sig
type t
val cx : t cx
val handler : t hnd
end
Ближайшим к вашей попытке будет:
datatype 'a cx = CX of { foo : string, handler : 'a hnd }
withtype 'a hnd = 'a cx -> 'a cx
Однако для доступа к записи требуется сопоставление с образцом. Определение функций доступа может сделать это более удобным.
Создание алгебраического типа данных с помощью одного конструктора работает для меня в SML / NJ, без необходимости определять несколько типов:
datatype 'a cx = CX of { foo : string, handler : 'a cx -> 'a cx }
type
не работает, потому что он просто определяет псевдоним (например, typedef
в C), который не может быть рекурсивным.