На этот раз у меня есть следующие определения:
data Color = Red | Green | Blue
deriving (Show, Eq)
data Suit = Club | Spade | Diamond | Heart
deriving (Show, Eq)
class Eq a => Eq (Cycle a) where
step :: a -> a
stepMany :: Integer -> a -> a
stepMany 0 x = x
stepMany steps x = stepMany (steps - 1) (step x)
instance Eq Color => Cycle Color where
step color
| color == Red = Green
| color == Green = Blue
| color == Blue = Red
instance Eq Suit => Cycle Suit where
step suit
| suit == Club = Spade
| suit == Spade = Diamond
| suit == Diamond = Heart
| suit == Heart = Club
Моя проблема в том, что линия
class Eq a => Eq (Cycle a) where'='"
выдает ошибку
Unexpected type `Cycle a'
In the class declaration for `Eq'
A class declaration should have form
class Eq a where ...
|
7 | class Eq a => Eq (Cycle a) where
|
В: Что я здесь делаю не так?
Обновленный код по-прежнему не выдает сообщение об ошибке, указанное в OP. Сообщение об ошибке: "Неожиданный тип `Cycle a' В объявлении класса для `Eq' Объявление класса должно иметь форму class Eq a, где..."
Несвязанный: хотя в этом случае вы смогли реализовать step с помощью == Red и подобных уравнений, вместо этого обычно лучше использовать сопоставление с образцом. step Red = Green ; step Green = Blue ; .... С более сложными типами == не работает, а сопоставление с образцом — простое общее решение этой задачи.
@chi Попробовал. Сопоставление с образцом не исправляет ошибку, с которой я сталкиваюсь.

Во-первых, используйте это, чтобы объявить Cycle. Это объявляет класс типа Cycle с ограничением Eq. class Eq a => Eq (Cycle a) where не является допустимым синтаксисом для объявления ни Cycle, ни Eq.
class Eq a => Cycle a where
...
Затем используйте это, чтобы объявить его экземпляр. Вы не можете написать Eq Color =>, потому что Color — это жесткий тип. Компилятор выдаст ошибку, если Color не является экземпляром Eq, в то время как вы пытаетесь сделать его экземпляром Cycle.
instance Cycle Color where
...
Окончательный код будет таким.
data Color = Red | Green | Blue
deriving (Show, Eq)
data Suit = Club | Spade | Diamond | Heart
deriving (Show, Eq)
class Eq a => Cycle a where
step :: a -> a
stepMany :: Integer -> a -> a
stepMany 0 x = x
stepMany steps x = stepMany (steps - 1) (step x)
instance Cycle Color where
step color
| color == Red = Green
| color == Green = Blue
| color == Blue = Red
instance Cycle Suit where
step suit
| suit == Club = Spade
| suit == Spade = Diamond
| suit == Diamond = Heart
| suit == Heart = Club
Та же ошибка сохраняется.
Хм, все заработало, когда я вставил приведенный выше код в test.hs и загрузил его в ghci 9.2.5 (:l test.hs). Возможно, вы захотите добавить подробности о том, как вы скомпилировали или загрузили его в свой вопрос.
Вам не нужно ограничение Eq для Cycle, а также для Color и Suit. Вы можете просто написать модуль следующим образом:
data Color = Red | Green | Blue
deriving (Show, Eq)
data Suit = Club | Spade | Diamond | Heart
deriving (Show, Eq)
class Cycle a where
step :: a -> a
stepMany :: Integer -> a -> a
stepMany 0 x = x
stepMany steps x = stepMany (steps - 1) (step x)
instance Cycle Color where
step color
| color == Red = Green
| color == Green = Blue
| color == Blue = Red
instance Cycle Suit where
step suit
| suit == Club = Spade
| suit == Spade = Diamond
| suit == Diamond = Heart
| suit == Heart = Club
Почему ==, а не сопоставление с образцом? (озадаченный)
@н.м. Я скопировал код OP и внес минимальные изменения, необходимые для его работы. OP, IIRC, новичок в Haskell (в этом нет ничего плохого - мы все когда-то были новичками), поэтому я считаю дидактически целесообразным сначала решить самую насущную проблему. Одно дело за раз...
Код примера не определяет
Cycle, поэтому я не могу воспроизвести обнаруженную проблему.Eq, однако, не определяет функциюstep, так что это одна проблема.