Объявление типов данных

У меня есть тип данных, который я использую для представления строк столбцов и столбцов строк:

data Object a = Row a
                |Column a

data Row a = Object a
             | Left(Row a)(Row a)

data Column a = Object a
             | Above(Column a)(Column a)


testfunction::Object a->String
testfunction Row(Left(c)(d)) = "Recognized row"

Я хотел бы знать, как я могу заявить, что конструктор в определении типа данных Object может «содержать» любые конструкторы, которые определены в другом месте, а другой конструктор в определении типа данных Object может «содержать» другой набор конструкторов.

So:

data Object a = Object1(Set1 a)
                | Object2(Set2 a)

data Set1 a = A a| B a| C a| D a
data Set2 a = X a| Y a| Z a

Таким образом, единственными допустимыми комбинациями являются Объект1(A a) Объект1(B a) Объект1(C a) Объект1(D a), Объект2(X a), Объект2(Y a) и Объект2(Z a)


person Lethi    schedule 09.09.2012    source источник
comment
Обратите внимание, что вы должны заключать скобки снаружи: цель состоит в том, чтобы сгруппировать выражения, а не вызывать функции. то есть testfunction (Row (Left c d)).   -  person huon    schedule 10.09.2012


Ответы (1)


Ваш тип Object a работает для всех типов a. Таким образом, если у вас есть значение Object a (как в вашей функции), вы ничего не знаете о том, что такое a, в частности, вы не знаете, что это значение типа Row a!

Теперь это немного сбивает с толку, потому что вы указали Row дважды — как тип и как конструктор типа Object. Эти двое никак не связаны. То есть в

data Object a = Row a

ничто не заставляет Row a содержать значение типа Row.

Самое простое исправление - и, вероятно, то, что вы на самом деле хотели написать, - это:

data Object a = Row (Row a)
              | Column (Column a)

это немного сбивает с толку, потому что вы видите Row и Column дважды, но каждый раз они означают разные вещи. Было бы понятнее, если бы вы написали это как-то так:

data Object a = ObjRow (Row a)
              | ObjColumn (Column a)

(Эти конкретные имена не очень хороши, потому что я не мог придумать, как их назвать, но, надеюсь, они делают различие ясным.)

После того, как вы определите Object таким образом, вы сможете сопоставлять шаблоны так, как хотите.

person Tikhon Jelvis    schedule 09.09.2012
comment
Значит ли это, что если бы у меня было 8 объектов на уровне объекта, и все они могли бы содержать друг друга (например, строка содержит столбец, а столбец может содержать строку), нет простого способа сказать, что все 8 объектов могут содержать декартово произведение друг друга, кроме как сделать 64 конструктора? Другими словами, если Object1 может содержать Object 2, 3, 4, 5, 6, 7, 8, а Object 2 может содержать Object 1, 3, 4, 5, 6, 7, 8, нет более простого способа объявить этот другой объект. чем выписывать 64 возможности в один конструктор? - person Lethi; 10.09.2012
comment
Отредактируйте мой комментарий выше, что, если бы я хотел только смоделировать рекурсивное сдерживание между подмножеством объектов 1-8. В идеале я хотел бы сгруппировать объекты 1-5 в их собственное определение, а затем, исходя из моего утверждения выше, разрешить объектам 1-8 содержать объекты 1-5? - person Lethi; 10.09.2012