В Haskell я могу сделать числовые литералы не полиморфными по умолчанию?

Это, вероятно, невозможно, так как я уже проверил список всех расширений GHC, и этого там нет, но я думал, что попрошу на всякий случай.

Есть ли способ сделать это так, чтобы 2 имел тип Int (или Integer), а не обычный Num a => a?

(Причина, по которой мне хотелось бы, чтобы это поведение было более ясным, и сделать вывод типа более вероятным (esp с типами классов). Я всегда мог писать (2:: Int) всюду, но я бы предпочел "более безопасное" поведение будет менее явным)

Ответ 1

Существует (немного оскорбительный и неудобный) способ сделать это с помощью расширений GHC.

{-# LANGUAGE RebindableSyntax #-}

import qualified Prelude as P
import Prelude hiding (Num(..))

fromInteger :: Integer -> Integer
fromInteger = id

В GHCi:

> :set -XRebindableSyntax
> :t 2
2 :: Integer

Если расширение RebindindableSyntax включено, GHC будет использовать все, что fromInteger находится в области обработки числовых литералов. Единственное ограничение состоит в том, что он должен принимать аргумент типа Integer (фактически, даже это не требуется, но если это не так, вы получите ошибку типа из числовых литералов).

Обратите внимание, что поскольку стандартный fromInteger является частью класса Num, вам может потребоваться взломать некоторые вещи, чтобы они работали правильно.

Ответ 2

Я думаю, что я должен добавить "default()" к этим ответам, хотя я думаю, что gatoatigrado упомянул об этом попутно. В стандарте Haskell 98 есть раздел раздел 4.3.4, который в конце концов описывает, как изменить некоторые значения по умолчанию Num a = > a. Неявный невыполненный порядок задается

 default (Integer, Double)

и может быть изменена, например. положив

 default (Int)

или

 default ()

в исходном файле.