Непоследовательное поведение fromIntegral в GHCi

Я надеялся, что кто-нибудь сможет объяснить следующее поведение GHCi при использовании функции fromIntegral:

Prelude> let x = 1 :: Integer                                                                                                                                                    
Prelude> :t x                                                                                                                                                                    
x :: Integer                                                                                                                                                                     
Prelude> sqrt $ fromIntegral x                                                                                                                                                   
1.0                                                                                                                                                                              
Prelude> let y = fromIntegral x                                                                                                                                                  
Prelude> sqrt y                                                                                                                                                                  

<interactive>:181:1:                                                                                                                                                             
No instance for (Floating Integer)                                                                                                                                           
  arising from a use of `sqrt'                                                                                                                                               
Possible fix: add an instance declaration for (Floating Integer)                                                                                                             
In the expression: sqrt y                                                                                                                                                    
In an equation for `it': it = sqrt y                                                                                                                                         

Какая разница, устанавливаю ли я y, а затем беру его sqrt или сразу беру sqrt?


person Eyal    schedule 11.07.2012    source источник
comment


Ответы (1)


fromIntegral является полиморфным по типу возвращаемого значения. Таким образом, можно ожидать, что тип y в вашем коде будет Num a => a. Этот тип позволит вам без проблем использовать y в качестве аргумента для sqrt.

Однако из-за ограничения мономорфизма тип y не может быть полиморфным. Поэтому по умолчанию используется тип Num по умолчанию, который равен Integer.

Когда вы выполняете sqrt $ fromIntegral x, ограничение мономорфизма не применяется, потому что оно применяется только к глобальным переменным, и на этот раз вы не сохраняете результат fromIntegral в переменной.

Вы можете решить эту проблему, либо добавив подпись типа к y (let y :: Num a => a; y = fromIntegal x), либо отключив ограничение мономорфизма.

person sepp2k    schedule 11.07.2012
comment
Чтобы отключить ограничение, добавьте {-# LANGUAGE NoMonomorphismRestriction #-} в начало файла или введите :set -XNoMonomorphismRestriction в GHCi. - person Jeff Burka; 12.07.2012
comment
Обычно считается хорошей идеей поместить :set -XNoMonomorphismRestriction в ваш .ghci, так как это в основном проблема в REPL. Использование его в одной из ваших программ требуется реже и не всегда является хорошей идеей (поскольку это может мешать совместному использованию). - person Jedai; 12.07.2012