Определить конструктор для нового типа - PullRequest
4 голосов
/ 03 сентября 2011

У меня есть тип

class IntegerAsType a where
  value :: a -> Integer

data T5
instance IntegerAsType T5 where value _ = 5

newtype (Num a, IntegerAsType n) => PolyRing a n = PolyRing [a]

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

Например, я мог бы захотеть принять только первые три элемента аргумента к значению PolyRingконструктор.

Я попытался добавить, используя предложение where в конце объявления newtype, но это не скомпилировалось.

Я также попробовал:

(PolyRing xs) = PolyRing [2, 3, 5, 7]

в качестве примера игрушки.Я думаю, это должно игнорировать аргумент конструктора значений и всегда иметь значение [2,3,5,7].Код компилируется, но мой «пользовательский» конструктор не действует.

Можно ли указать конструктор для нового типа?

1 Ответ

7 голосов
/ 03 сентября 2011

Я думаю, что вы ищете Умный конструктор .

PolyRing Базовый конструктор с заглавной буквы не может быть перегружен.Но то, что вы можете сделать, это:

polyRing :: (Num a, IntegerAsType n) => [a] -> PolyRing a n
polyRing = PolyRing . take 3

Или, что еще лучше:

polyRing :: (Num a, IntegerAsType n) => [a] -> Maybe (PolyRing a n)
polyRing (a:b:c:_) = Just $ PolyRing [a, b, c]
polyRing _         = Nothing

Чтобы запретить кому-либо использовать конструктор PolyRing напрямую, объявление экспорта вашего модуля вверхуфайла может выглядеть следующим образом:

module PolyRing (
 PolyRing (), -- Export the PolyRing type but not constructor
 polyRing     -- Your smart constructor
) where

В OO единицей инкапсуляции является класс, но в Haskell это модуль.

...