#haskell #compiler-errors #typeclass
Вопрос:
Я новичок в Хаскелле и в настоящее время пытаюсь понять, как писать свои собственные типовые классы. Это то, что у меня есть до сих пор:
data Signal = X | O
class Show a where
show :: a -> String
instance Show Signal where
show X = "X"
show O = "O"
И когда я пытаюсь это сделать, я получаю ошибку :
Ambiguous occurrence `Show'
It could refer to
either `Prelude.Show',
or `Main.Show
И я не могу понять, почему это происходит, потому что я думал, что весь смысл классов типов в Haskell в том, что это делает возможной перегрузку функций? Заранее спасибо за вашу помощь!
Комментарии:
1. Да, но вы не должны определять класс типов в своем модуле.
2. Тогда где же мне вместо этого определить класс типов?
3. он уже определен в
Prelude
, вы здесь определяете второй, вот что говорит компилятор: теперь существует два класса типов, поэтому неясно, для какого из них вы определяете экземпляр..
Ответ №1:
И я не могу понять, почему это происходит, потому что я думал, что весь смысл классов типов в Haskell в том, что это делает возможной перегрузку функций?
Это правильно, но здесь вы определяете новый класс типов, Show
который конфликтует с тем, который находится в Prelude
.
Если вы определяете экземпляр, то неясно, к какому Show
классу он относится. К тому, который определен в Prelude
(где многие типы являются членами), или тому, который вы определили в своей собственной программе.
Таким образом, вы можете определить это как:
data Signal = X | O
-- no definition for Show
instance Show Signal where
show X = "X"
show O = "O"
Если вы хотите определить свой собственный класс типов, вы можете работать с:
import Prelude hiding (Show)
data Signal = X | O
class Show a where
show :: a -> String
instance Show Signal where
show X = "X"
show O = "O"
но это, вероятно, не очень хорошая идея, поскольку все остальные типы не являются членами нового класса типов, а только членами того, который определен в Prelude
.
Таким образом, класс типов можно рассматривать как интерфейс на таких языках, как Java: ваши типы данных могут быть членами класса типов, если они определяют экземпляр, который, таким образом, определяет реализацию методов (здесь show
). Но если два интерфейса имеют одно и то же имя, это не значит, что это один и тот же интерфейс.
Комментарии:
1. Есть ли какой-нибудь способ перезаписать класс типов шоу из Прелюдии?
2. @Rosarosa: вы можете
import Prelude hiding (Show)
, это предотвратит загрузкуShow
класса типов, и, таким образом, вы сможете определить свой собственный.3. @Rosarosa: идея заключается в том, что вы определяете несколько экземпляров для класса типов, а не несколько классов типов с одинаковыми именами.