Ошибка при компиляции печати Любое значение

Я пытаюсь скомпилировать простой фрагмент кода.

main = (putStrLn . show) (Right 3.423)

Скомпилируйте результаты в следующей ошибке:

No instance for (Show a0) arising from a use of `show'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
  instance Show Double -- Defined in `GHC.Float'
  instance Show Float -- Defined in `GHC.Float'
  instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
    -- Defined in `GHC.Real'
  ...plus 42 others
In the second argument of `(.)', namely `show'
In the expression: putStrLn . show
In the expression: (putStrLn . show) (Right 3.423)

Когда я выполняю тот же фрагмент из ghci, все работает как ожидалось.

Prelude> let main = (putStrLn . show) (Right 3.423)
Prelude> main
Right 3.423

Итак, вопрос в том, что происходит?

1 ответ

Решение

Проблема в том, что GHC не может определить, какой полный тип Right 3.423 есть, он может только определить, что он имеет тип Either a Double и случай Show за Either похоже instance (Show a, Show b) => Show (Either a b) , Без этого дополнительного ограничения на Either a Double GHC не знает, как его распечатать.

Причина, по которой он работает в интерактивном режиме, заключается в страшном ограничении мономорфизма, которое делает GHCi более агрессивным по умолчанию, который он выбирает. Это можно отключить с помощью :set -XNoMonomorphismRestriction и это станет по умолчанию в будущих версиях GHC, так как это создает много проблем для начинающих.

Решение этой проблемы - поставить подпись типа на Right 3.423 в вашем исходном коде, как

main = (putStrLn . show) (Right 3.423 :: Either () Double)

Здесь я только что использовал () за a, поскольку нас это все равно не волнует, и это "самый простой" тип, который можно показать. Вы могли бы поставить String или же Int или же Double или что вы там хотите, пока это реализует Show,

Совет, putStrLn . show это именно определение print так что вы можете просто сделать

main = print (Right 3.423 :: Either () Double)


Как указывает @ØrjanJohansen, это не ограничение мономорфизма, а ExtendedDefaultRules расширение, которое использует GHCi, которое по сути делает именно то, что я сделал выше, и пихает () в переменные типа, чтобы заставить вещи работать в интерактивном сеансе.

Другие вопросы по тегам