Почему некоторые операторы меняют свой тип при назначении?


Когда я спрашиваю тип оператора+, это так, как вы ожидаете

Prelude> :t (+)
(+) :: Num a => a -> a -> a

Когда я присваиваю оператор переменной, то сигнатуры типа меняются

Prelude> let x = (+)
Prelude> :t x
x :: Integer -> Integer -> Integer

Почему изменяется тип оператора, когда он присваивается?

1 3

1 ответ:

Это и есть "страшное ограничение мономорфизма". По существу, когда вы определяете

  1. новое имя верхнего уровня, которое
  2. не похоже на определение функции
Затем, по умолчанию, Хаскелл пытается быть умным и выбрать менее чем полностью общий тип для него. Изначально причины были в том, чтобы сделать Haskell более удобным в использовании (без него, возможно, легче писать программы с неоднозначными типами), но в последнее время он, кажется, просто сбивает всех с толку, так как это очень неожиданно поведение.

Резолюция?

  1. Используйте GHC 7.8. После версии 7.8, GHCi сеансы автоматически...
  2. Use-Xnomonomorphismrestrication, который отключает это поведение, или
  3. Укажите аннотацию типа

    let { x :: Num a => a -> a -> a; x = (+) }
    

В нормальном коде Хаскелла метод (3) наиболее рекомендуется. При использовании GHCi, (1) и (2) более удобны.