#haskell #hugs
#haskell #объятия
Вопрос:
Наткнулся на это, играя с Haskell, и я в тупике:
Hugs> :type (x -> x^2)
x -> x ^ 2 :: (Integral a, Num b) => b -> b
Что a
там происходит? Как я должен это читать? Если я введу то же самое в GHCi, это даст мне результат, который я ожидаю:
Prelude> :type (x -> x^2)
(x -> x^2) :: Num a => a -> a
Это ошибка в Hugs?
Комментарии:
1. @CatPlusPlus: по крайней мере, это не Gofer 🙂 Я полагаю, что многие курсы FP были написаны, когда в GHC не было GHCi, и были сложными (и большими! 50 МБ!) для установки в Windows. Весь смысл Hugs заключался в том, чтобы заставить людей быстро использовать Haskell. Hugs также использовался для поддержки нескольких интересных расширений Haskell, в частности TREX. Gofer, предшественник Hugs, был первым, кто ввел многопараметрические классы типов, если я правильно помню.
2. Если подумать, Gofer был детищем Марка П. Джонса, написанным для экспериментов с модными классами типов, такими как
Functor
иMonad
. До этого (здесь мы говорим о Haskell 1.3) классы типов могли быть объявлены только для типов*
. Примерно в 1992 году происходило много событий. С другой стороны, сейчас это все еще очень весело: GADTs, семейства типов и типы ограничений, о боже!3. По-видимому, профессора компьютерных наук используют Hugs; Я слышал, что это хорошая платформа для обучения из-за подробных сообщений об ошибках [требуется цитирование].
4. Это википедия сейчас или что-то в этом роде? xkcd.com/285
Ответ №1:
Integral
Ограничение исходит из показателя степени 2
. Помните, что в Haskell целочисленные литералы на самом деле являются полиморфными значениями типа Num a => a
. Затем компилятор делает вывод, что, поскольку он используется как показатель (^) :: (Num a, Integral b) => a -> b -> a
степени, он должен быть более ограниченного типа Integral a => a
.
Чтобы избавить вас от необходимости устранять неоднозначность числовых литералов по всему вашему коду, Haskell использует тип по умолчанию для выбора разумного конкретного типа для любых неограниченных числовых типов. В этом случае это будет Integer
. Разница, по-видимому, заключается в том, что :type
in Hugs сообщает о предполагаемом типе до того, как это произойдет, в то время как GHCi сообщает о типе после применения типа по умолчанию.
Если вы сами укажете конкретный тип для экспоненты, дополнительное ограничение исчезнет.
Hugs> :type (x -> x^(2 :: Integer))
x -> x ^ 2 :: Num a => a -> a
Комментарии:
1. Хотя это немного странно, поскольку
(Integral a, Num b) => b -> b
не было бы допустимым типом для явного указания чего-либо, посколькуa
он не используется.2. Очень интересно. Я бы ожидал, что программа отклонит ее как неоднозначную, если она не введет default.
Ответ №2:
Это своего рода предположение, но это может быть связано с типом (^)
. :t (^)
возвращает в ghci (^) :: (Num a, Integral b) => a -> b -> a
. Я предполагаю, что hugs видит, что вторым аргументом ^
должен быть an Integral
, и хотя этот аргумент является просто константой 2, он включает ограничение в сигнатуру типа.
Комментарии:
1. Да, отклонение в печати типов hugs от ghci. Вероятно, по умолчанию должно быть от 2 до Integer и использоваться только базовый тип.