Ошибка множественного объявления типа суммы haskell

data A=A
data B=B
data AB=A|B

Что делает тип суммы AB из A и B.

но последняя строка вызывает ошибку компиляции "несколько объявлений B"

Я также пробовал что-то вроде этого:

data A=Int|Bool

Он компилируется. но почему ghc запрещает мне создавать типы сумм для пользовательских типов?


person doofin    schedule 12.09.2015    source источник
comment
Ух ты! Это редактирование полностью изменило детали вопроса, из-за чего все ответы выглядели немного глупо. Это не совсем рекомендуемый способ; вместо этого, если вы обнаружите, что вы все еще в замешательстве после своего первого вопроса, откройте новый вопрос с подробностями о вашем новом вопросе, о том, чем он отличается от предыдущего и почему вы все еще в замешательстве.   -  person Daniel Wagner    schedule 12.09.2015
comment
извините, предыдущий на самом деле упрощенный ... и после некоторых экспериментов я считаю, что лучше опубликовать оригинальный, извините .. спасибо за подробный набор текста! Вы хотите обновить свой ответ?   -  person doofin    schedule 12.09.2015
comment
@doofin: нет... ты должен отменить свое редактирование и открыть новый вопрос   -  person Michael    schedule 12.09.2015


Ответы (4)


Вас обманывают. Вы думаете, что когда вы пишете data A=Int|Bool, вы говорите, что значение типа A может быть значением типа Int или значением типа Bool; но вы на самом деле говорите, что есть два новых конструктора уровня значений с именами Int и Bool, каждый из которых вообще не содержит информации, типа A. Точно так же вы думаете, что data AB=A|B говорит, что вы можете иметь либо тип A, либо тип B, но на самом деле вы говорите, что вы можете иметь либо значение A, либо значение B.

Главное, о чем следует помнить, это то, что существует два пространства имен, уровень типов и уровень терминов, и что они различны.

Вот простой пример того, как это сделать правильно:

data A=A
data B=B
data AB=L A|R B

В последней строке объявляются два новых конструктора уровня терминов, L и R. Конструктор L содержит значение type A, а конструктор R содержит значение type B.

Вам также может понравиться тип Either, определяемый следующим образом:

data Either a b = Left a | Right b

Вы можете использовать это для реализации своего AB, если хотите:

type AB = Either A B

Точно так же вы можете использовать Either Int Bool для объединения тегов Int и Bool.

person Daniel Wagner    schedule 12.09.2015
comment
Учитывая, что ни A, ни B не несут дополнительной информации, можно было бы, вероятно, полностью отбросить их и использовать data AB = A | B, но это трудно увидеть без дополнительного кода. - person Zeta; 12.09.2015
comment
@Zeta Я предполагаю, что data A=A и data B=B были просто заполнителями для более интересных типов данных. - person Daniel Wagner; 12.09.2015

Когда вы говорите data AB = A | B, вы имеете в виду не типы A и B, а скорее определяете конструкторы данных A и B. Они конфликтуют с конструкторами, определенными в предыдущих строках.

Если вы хотите создать тип AB, представляющий собой сумму A и B, вы должны предоставить конструкторы данных, которые обертывают типы A и B, например:

data AB = ABA A | ABB B
person Rein Henrichs    schedule 12.09.2015

Потому что тип значения, созданного с помощью конструктора данных A или B, будет неоднозначным. Например, когда у меня есть a = B, каков тип a? Это A или AB?

Вам следует рассмотреть возможность использования другого конструктора данных следующим образом:

data A = MkA
data B = MkB
data AB = A A | B B
person Evan Sebastian    schedule 12.09.2015
comment
Я думаю, вы имели в виду data AB = A A | B B. Ведь это должна быть сумма типа А и Б. - person Zeta; 12.09.2015
comment
А, точно, спасибо за поправку, хотел это написать - person Evan Sebastian; 12.09.2015

Типы суммы должны быть помечены. a+a нужно сделать две инъекции от a.

Чтобы понять, как работают алгебраические типы данных, рассмотрим простой пример:

data X = A | B C

Это определяет конструктор нового типа X вместе с конструкторами данных A и B. Конструктор B принимает/содержит аргумент типа C.

Основной канонический тип суммы в Haskell — Either:

data Either a b = Left a | Right b
person dfeuer    schedule 12.09.2015