Почему этот экземпляр Show в Haskell (Hugs) вызывает ошибку переполнения стека? - PullRequest
3 голосов
/ 23 октября 2011

Ниже приведен полиморфный тип данных в Haskell, интерпретируемый Хагсом. Я пытаюсь создать экземпляр Show for Equality.

Объявление экземпляра говорит, что если тип "a" находится в Show, тогда равенство a находится в Show. Он должен вывести два аргумента в конструктор Equals a b в форме "a = b".

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
show (Equals a b) = a ++ " = " ++ b

Тем не менее, введя что-то в Hugs наподобие "(Equality 9 9)", вы получите:

ОШИБКА - переполнение стека C

Итак, я попытался сделать отступ в строке "show (Equals a b) ..." с парой пробелов). Я не уверен, какая будет разница, но просто поигрался и получил:

Inferred type is not general enough
*** Expression    : show
*** Expected type : Show (Equality a) => Equality a -> String
*** Inferred type : Show (Equality [Char]) => Equality [Char] -> String

Может кто-нибудь объяснить, почему происходят эти ошибки, или предложить лучший способ реализации этого экземпляра шоу?

Спасибо!

Ответы [ 3 ]

3 голосов
/ 23 октября 2011

Ваш код имеет неправильный отступ. Он определяет пустой Show экземпляр:

instance (Show a) => Show (Equality a) where

и отдельная функция верхнего уровня show:

show (Equals a b) = a ++ " = " ++ b

типа Equality [Char] -> [Char]. Поэтому, когда вы пытаетесь использовать ваш экземпляр Show, определение по умолчанию show из Show класса выбирается. Глядя на код:

showsPrec _ x s = show x ++ s
show x          = showsPrec zeroInt x ""

вы можете видеть, что значение по умолчанию show определяется в терминах showsPrec, что в свою очередь определяется в терминах show. Это объясняет, почему ваша программа входит в бесконечный цикл.

Чтобы исправить код, сделать соответствующий отступ и добавить недостающие вызовы к show, чтобы исправить ошибку типа (что связано с тем, что вы не можете объединить произвольный тип a со строкой - вы должны сначала преобразовать a в строку):

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Тестирование:

*Main> show (Equals 9 9)
"9 = 9"
1 голос
/ 23 октября 2011

Отступ имеет значение из-за странной порой чувствительности пробелов в Haskell.Без отступа компилятор не может сказать, что следующий оператор относится к where.

Ошибка, которую вы получаете, заключается в том, что полиморфный тип, не имеющий ограничений, не гарантирует, что a и b может объединяться со строкой "=".Что делать, если у вас есть Equals 1 1.Как бы вы связали это, не создавая сначала строки Ints?

Однако, если вы сначала show a и b, все сработает, потому что show превращает значения во что-то, что может быть объединено со строкой.

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
    show (Equals a b) = (show a) ++ " = " ++ (show b)
1 голос
/ 23 октября 2011

Я думаю, что ваша проблема в том, что вы не вызывали функцию show для аргументов a и b.Я сделал это в GHC, но я думаю, что это должно работать:

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Тогда:

> Equals 9 9
9 = 9
...