Подпись типа Hugs содержит дополнительные ограничения типа?

#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 и использоваться только базовый тип.