Классовые проблемы с Haskell

На этот раз у меня есть следующие определения:

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
  |

В: Что я здесь делаю не так?

Код примера не определяет Cycle, поэтому я не могу воспроизвести обнаруженную проблему. Eq, однако, не определяет функцию step, так что это одна проблема.

Mark Seemann 12.06.2023 08:41

Обновленный код по-прежнему не выдает сообщение об ошибке, указанное в OP. Сообщение об ошибке: "Неожиданный тип `Cycle a' В объявлении класса для `Eq' Объявление класса должно иметь форму class Eq a, где..."

Mark Seemann 12.06.2023 09:02

Несвязанный: хотя в этом случае вы смогли реализовать step с помощью == Red и подобных уравнений, вместо этого обычно лучше использовать сопоставление с образцом. step Red = Green ; step Green = Blue ; .... С более сложными типами == не работает, а сопоставление с образцом — простое общее решение этой задачи.

chi 12.06.2023 10:04

@chi Попробовал. Сопоставление с образцом не исправляет ошибку, с которой я сталкиваюсь.

coderodde 12.06.2023 11:18
Сила классов Java: сравнение с языком C
Сила классов Java: сравнение с языком C
Абстракция" - это процесс упрощения сложных сущностей или концепций реального мира с целью их применения в форме программирования. В Java класс...
2
4
116
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во-первых, используйте это, чтобы объявить 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

Та же ошибка сохраняется.

coderodde 12.06.2023 11:19

Хм, все заработало, когда я вставил приведенный выше код в test.hs и загрузил его в ghci 9.2.5 (:l test.hs). Возможно, вы захотите добавить подробности о том, как вы скомпилировали или загрузили его в свой вопрос.

snak 12.06.2023 11:26
Ответ принят как подходящий

Вам не нужно ограничение 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

Почему ==, а не сопоставление с образцом? (озадаченный)

n. m. 12.06.2023 12:30

@н.м. Я скопировал код OP и внес минимальные изменения, необходимые для его работы. OP, IIRC, новичок в Haskell (в этом нет ничего плохого - мы все когда-то были новичками), поэтому я считаю дидактически целесообразным сначала решить самую насущную проблему. Одно дело за раз...

Mark Seemann 12.06.2023 16:49

Другие вопросы по теме