> but its return value certainly doesn't depend only on its arguments
Note that value1 and value2 are not, and cannot possibly be, return values of notPurelyFunctional. The type of notPurelyFunctional says its return value has type IO Double, but value1 and value2 have type Double. IO Double is not Double, doesn't contain a Double, and cannot be converted to Double by a function call.
It sounds like you still think that the syntax "do x <- foo" means something like "let x be the result of some function call involving foo". Actually it can't be anything like that, it translates to something more compicated.
> If that were the case, then any operation on getLine would return the same value
Yes, and moreover, any operation on notPurelyFunctional 5.0 always returns the same value.
You have my honest word that I have some experience with Haskell and believe these things to be 100% true, with no wishy-washy philosophical caveats. I know exactly how to write an interpreter in which the machine representation of something like "notPurelyFunctional 5.0" will be immutable bit-for-bit, without using any dirty tricks like pointers to mutable memory. And I know that it's immutable in actual Haskell implementations as well.
Note that value1 and value2 are not, and cannot possibly be, return values of notPurelyFunctional. The type of notPurelyFunctional says its return value has type IO Double, but value1 and value2 have type Double. IO Double is not Double, doesn't contain a Double, and cannot be converted to Double by a function call.
It sounds like you still think that the syntax "do x <- foo" means something like "let x be the result of some function call involving foo". Actually it can't be anything like that, it translates to something more compicated.
> If that were the case, then any operation on getLine would return the same value
Yes, and moreover, any operation on notPurelyFunctional 5.0 always returns the same value.
You have my honest word that I have some experience with Haskell and believe these things to be 100% true, with no wishy-washy philosophical caveats. I know exactly how to write an interpreter in which the machine representation of something like "notPurelyFunctional 5.0" will be immutable bit-for-bit, without using any dirty tricks like pointers to mutable memory. And I know that it's immutable in actual Haskell implementations as well.