Алгебраические типы данных Haskell

У меня есть следующее для тега шрифта HTML:

data Color = HexColor Int | RGBColor Int Int Int | ColorString String deriving Show
data FontAttribute = Size Int | Face String | FontColor Color deriving Show
data Font = Font [FontAttribute] deriving Show

Я строю так:

Font [Size 23,Face "Arial",Color (RGBColor 240 23 43)]

Меня беспокоит то, что конструктору данных/значений FontColor, который имеет тип FontAttribute, требуется тип Color в качестве аргумента. Это означает, что Color является общим атрибутом типа для любого типа тега, а конкретный тег имеет определенное подмножество атрибутов (в данном случае Font имеет FontAttribute, который может быть Size, Face или FontColor). Есть ли более ясный способ выразить это, или моя реализация верна?


person Aram Kocharyan    schedule 11.03.2012    source источник
comment
Предполагается ли, что можно создавать Font, описываемые любым числом и комбинацией, или FontAttribute? Font [Face "Arial", Face "Impact"] не кажется очень полезным...   -  person    schedule 11.03.2012
comment
Да, любой действительный список. Вы можете сделать то же самое в XHTML и CSS, я думаю, что то, что происходит, зависит от реализации. Обычно браузер использует последнее значение. Меня больше беспокоила иерархия типов.   -  person Aram Kocharyan    schedule 11.03.2012
comment
Итак, вы хотите ограничить использование Color исключительно с конструктором FontColor? Это твоя забота? Кстати, скобки вокруг [FontAttribute] не нужны.   -  person Alp Mestanogullari    schedule 12.03.2012
comment
Нет, я бы хотел, чтобы Color был универсальным, но мне не нравится генератор данных FontColor Color, есть ли более четкий способ выразить, что FontColor является цветом, а также FontAttribute. Я не уверен.   -  person Aram Kocharyan    schedule 12.03.2012


Ответы (1)


Цвет — это просто тип, а не атрибут. В системе типов нет ничего, что указывало бы на то, что Color имеет какую-либо особую связь с FontAttribute. Все, что происходит, когда вы определяете тип данных FontAttribute, заключается в том, что он создает конструктор с именем FontColor, который является обычной функцией со следующей сигнатурой типа:

FontColor :: Color -> FontAttribute

Итак, если вы объявили какой-то новый тип с именем Link:

data LinkAttrubute = LinkColor Color | ...

Затем Color можно было бы сохранить и в LinkAttribute. Конструктор не подразумевает исключительную связь только с этим типом данных. Все, что говорит ваш тип данных FontAttribute, это то, что он МОЖЕТ содержать только цвет.

В Haskell нет встроенной концепции атрибутов, потому что в нем нет встроенной концепции объектов. ОДНАКО вы можете моделировать атрибуты, используя тип Lens из пакета data-lens (или fclabels). Я бы связал вам пакеты, но я с телефона и это сложно.

person Gabriel Gonzalez    schedule 12.03.2012
comment
Спасибо, это то, что я хотел. Вы хотели бы, чтобы Color был универсальным и применимым к любому конструктору данных. - person Aram Kocharyan; 12.03.2012