Подтвердить что ты не робот

Списки типов данных: "не удалось вывести (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)]
4b9b3361

Ответ 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]

Но в конечном счете это зависит от того, что вы пытаетесь выполнить.