Это вариант пресловутой проблемы show . read
.Классическая версия использует
read :: Read a => String -> a
show :: Show a => a -> String
, поэтому композиция может показаться простым старым преобразователем String
moo :: String -> String
moo = show . read
за исключением того, что в программе нет информации для определения типа в серединеследовательно, что до read
, а затем show
.
Ambiguous type variable `b' in the constraints:
`Read b' arising from a use of `read' at ...
`Show b' arising from a use of `show' at ...
Probable fix: add a type signature that fixes these type variable(s)
Пожалуйста, обратите внимание, что ghci делает кучу сумасшедших лишних настроек по умолчанию, решая неоднозначность произвольно.
> (show . read) "()"
"()"
Ваш C
class является вариантом Read
, за исключением того, что он декодирует Int
вместо чтения String
, но проблема, по сути, та же.не само по себе большое дело.Это неоднозначный вывод экземпляра , вот в чем проблема.Рассмотрим
poo :: String -> a -> a
poo _ = id
qoo :: (a -> a) -> String
qoo _ = ""
roo :: String -> String
roo = qoo . poo
При построении roo
никогда не определяется, каким должен быть тип в середине, и не является roo
полиморфным в этом типе.Вывод типа не решает и не обобщает переменную!Тем не менее,
> roo "magoo"
""
это не проблема, потому что конструкция параметрическая в неизвестном типе.Тот факт, что тип не может быть определен, приводит к тому, что тип не может иметь значение .
Но неизвестные экземпляры явно имеют значение.Результат полноты для вывода типа Хиндли-Милнера опирается на параметричность и, таким образом, теряется при добавлении перегрузки.Давайте не будем плакать об этом.