Списки типов данных: "не удалось вывести (a ~ SomeType) из контекста (SomeTypeclass a)"
У меня есть следующая проблема с системой типа Haskell: я пытаюсь объявить тип данных и возвращать список, содержащий элементы этого типа, из функции. К сожалению, даже минимальный тестовый тест, например
data SampleType = SampleTypeConstructor
instance Show SampleType where
show x = "(SampleType)"
stList :: (Show a) => [a]
stList = [(SampleTypeConstructor)]
main = do {
putStrLn (show stList)
}
выходит из строя со следующим сообщением об ошибке от ghc-7.0.2 и ghc-7.1.20110327:
tcase.hs:7:12:
Could not deduce (a ~ SampleType)
from the context (Show a)
bound by the type signature for stList :: Show a => [a]
at tcase.hs:7:1-34
`a' is a rigid type variable bound by
the type signature for stList :: Show a => [a] at tcase.hs:7:1
In the expression: (SampleTypeConstructor)
In the expression: [(SampleTypeConstructor)]
In an equation for `stList': stList = [(SampleTypeConstructor)]
Ответы
Ответ 1
строка нарушения stList :: (Show a) => [a]
. Вы объявляете, что stList - это полиморфный список, содержащий любой элемент, который удовлетворяет ограничениям show. Но stList не является полиморфным списком! Это список SampleType
s. Поэтому удалите подпись и посмотрите, что ghci называет, или просто дайте ей правильную подпись: :: [SampleType]
.
Ответ 2
stList :: (Show a) => [a]
говорит, что для любого экземпляра Show
для любого типа a
вы возвращаете список элементов этого типа.
stList = [SampleTypeConstructor]
возвращает список SampleType
s, тогда как это список элементов, для которых существует экземпляр Show
, это не список, который работает для каждого выбора a
.
В реальности единственным жителем, которого вы, вероятно, найдете для этого типа, который не включает нижние части, является []
, потому что Show a
не предоставляет никакого механизма для построения a
.
Чтобы исправить это, вы можете сделать одну из нескольких вещей, в зависимости от вашей конечной цели.
Вы можете просто хотеть, чтобы stList
имел более узкий тип:
stList :: [SampleType]
Возможно, вы захотите создать какой-то тип типа
newtype Showable = Showable (Int -> String -> String)
который явно фиксирует соответствующую часть экземпляра Show. (Вы также можете сделать это с экзистенциальным типом, но эта версия - Haskell 98.)
instance Show Showable where
showsPrec d (Showable f) = f d
showable :: Show a => a -> Showable
showable a = Showable (\d -> showsPrec d a)
Затем вы можете составить список Showables.
stList :: [Showable]
stList = [showable SampleTypeConstructor]
Но в конечном счете это зависит от того, что вы пытаетесь выполнить.