Haskell, почему "Num x" требует "Показать x"?

Недавно я взглянул на Haskell, используя LYAH.

Я возился с типами классов и написал эту функцию быстрого тестирования:

foo :: (Num x) => x -> String
foo x = show x ++ "!"

Но это вызывает эту ошибку:

test.hs:2:9:
    Could not deduce (Show x) arising from a use of `show'
    from the context (Num x)
    bound by the type signature for foo :: Num x => x -> String
    at test.hs:1:8-29
    Possible fix:
      add (Show x) to the context of
        the type signature for foo :: Num x => x -> String

Но согласно ЛЯХ:

Чтобы присоединиться к Num, тип должен уже быть знакомым с Show и Eq.

Итак, если все в Num является подмножеством Show и Eq, почему мне нужно изменить подпись типа на foo :: (Num x, Show x) => x -> String, чтобы это работало? Нельзя ли сделать вывод, что a Num также является Show-able?

Ответ 1

Информация в LYAH устарела. В примечаниях для GHC 7.4.1 говорится:

Класс Num больше не имеет Eq или Show суперклассов.

Вам нужно будет написать

foo :: (Num x, Show x) => x -> String

(На самом деле, foo, который вы написали, не требует Num x, поэтому вы можете опустить это, чтобы избежать ненужного ограничения.)

Ответ 2

Он был, что экземпляр Num также был экземпляром Show и Eq, но больше не будет.

Вам также нужно добавить ограничение Show.

Ответ 3

Haskell, 98 и 2010 оба требуют, чтобы все экземпляры Num также были экземплярами Show и Eq. Это во многом случай истории.

GHC, самый популярный компилятор Haskell, расходится со стандартом здесь, не требуя никакой прагмы. Это было сделано, чтобы аппликативные функторы были экземплярами Num и пользовались преимуществами перегруженного синтаксиса.

Ответ 4

Не следует писать:

(Num x) => x -> String

Вместо

(Num x) x -> String

И насколько я знаю, это наследование, по крайней мере, устарело.