typeclass - Haskell arithmetic with literals - Stack Overflow

In Haskell, a standalone expression 3 + 5 means fromInteger (3 :: Integer) + fromInteger (5 :: Integer)

In Haskell, a standalone expression 3 + 5 means fromInteger (3 :: Integer) + fromInteger (5 :: Integer). In GHCi it is evaluated to fromInteger 8 of type Num a => a. It is clear that Haskell can calculate (3 :: Integer) + (5 :: Integer), but evaluating the original polymorphic expression seems to require some rule of the form fromInteger x + fromInteger y = fromInteger (x + y), and I don't see such rule in the Prelude. How exactly is the evaluation of 3 + 5 done in GHCi?

Does defaulting play a role here? It does not seem so because if I write default () at the prompt, then 3 + 5 is still computed correctly, while, for example, \(x :: Float) -> x^2 fails to typecheck. If I restore the default with default (Integer, Double), then \(x :: Float) -> x^2 typechecks as expected.

In Haskell, a standalone expression 3 + 5 means fromInteger (3 :: Integer) + fromInteger (5 :: Integer). In GHCi it is evaluated to fromInteger 8 of type Num a => a. It is clear that Haskell can calculate (3 :: Integer) + (5 :: Integer), but evaluating the original polymorphic expression seems to require some rule of the form fromInteger x + fromInteger y = fromInteger (x + y), and I don't see such rule in the Prelude. How exactly is the evaluation of 3 + 5 done in GHCi?

Does defaulting play a role here? It does not seem so because if I write default () at the prompt, then 3 + 5 is still computed correctly, while, for example, \(x :: Float) -> x^2 fails to typecheck. If I restore the default with default (Integer, Double), then \(x :: Float) -> x^2 typechecks as expected.

Share Improve this question asked Mar 23 at 8:58 Evgeny MakarovEvgeny Makarov 551 silver badge5 bronze badges 4
  • 1 If I write default () and then 3 + 5 in GHCi (9.6.6) then I do get an error. – Noughtmare Commented Mar 23 at 10:38
  • @Noughtmare You are right. I was using Emacs with Haskell mode, and sometimes in the interpreter it hides an error and prints the original expression and its type instead. I can't explain how I misread 3 + 5 :: Num a => a as 8 :: Num a => a. – Evgeny Makarov Commented Mar 23 at 13:54
  • 1 fromInteger 3 + fromInteger 5 does not evaluate to fromInteger 8. Write newtype T = T {t::Int}; instance Num T where fromInteger = T . fromInteger; x + y = T 0; then you can enter 3+5 and t it to see that you get 0 (the contained value of T 3+T 5), not 8 (the contained value of fromInteger (3+5)). – Daniel Wagner Commented Mar 23 at 15:17
  • 1 Fun fact: If you write default () and try to evaluate 8 in GHCi, you'll also get an error. Even just printing the value 8 requires a Show instance which needs a default type. – K. A. Buhr Commented Mar 23 at 17:04
Add a comment  | 

1 Answer 1

Reset to default 4

Yes, defaulting is how this works.

+ has type Num a => a -> a -> a. So 3 + 5 can indeed be used to write an expression for a value of type Num a => a. But that value will never actually be evaluated if we leave it as that type! We can't identify which code to run for + to evaluate the expression until we've determined which Num instance to use, so there is no way for 3 + 5 to be evaluated at the polymorphic type Num a => a . In fact if you actually create such a value it is internally represented as a function, where the parameter is a dictionary identifying the Num instance, and the body will use the dictionary's definition for + (and also for fromInteger to evaluate the literals 3 and 5, in fact; those can't be evaluated polymorphically either) to evaluate the expression.

When you just type 3 + 5 into GHCi, it might appear to have evaluated your expression polymorphically, as it will (with default settings) print 8. But what actually happens is that expression creates a value that doesn't evaluate the addition (internally represented as a function), and then when GHCi tries to print your last-entered value it can't do that without having actually evaluated it, so it applies defaulting to the use of the value during print. Defaulting (with default settings) comes up with Integer , so it passes the dictionary for Num Integer to the function representing 3 + 5, which can then use Integer addition to produce the Integer value 8.

If the same expression was used in a context requiring it to be a Double then the underlying function representing 3 + 5 would instead be passed the Num Double instance dictionary, and would then use Double addition to produce the Double value 8.0.

The result of the addition is never actually represented as a concrete polymorphic value with the type Num a => a. It only actually gets evaluated once a concrete type has been chosen and the instance dictionary passed in. If you haven't identified a concrete type then you would get an ambiguous type variable error if you ever needed to actually evaluate the expression (such as being able to print a concrete value), unless defaulting chooses a concrete type for you.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744292369a4567095.html

相关推荐

  • typeclass - Haskell arithmetic with literals - Stack Overflow

    In Haskell, a standalone expression 3 + 5 means fromInteger (3 :: Integer) + fromInteger (5 :: Integer)

    7天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信