Haskell purity and printing

This is what I "understand" so far ... Suppose we have these two values: a) \x->x + x b) \x->2 * x Because these to values are equal, all functions definable in Haskell must preserve this. This is why I am not allowed to define a function like h :: (a->b) -> (a->b) h x = x The reasons are very complicated, but it goes something like this: - when one put \x->x+x trough the function h, the compiler might change it to \x -> 2*x - when one put \x->2*x trough the function h, the compiler might change it to \x -> x + x And we all know that \x -> 2*x is not the same as \x->x+x and this is the reason one cannot define h in Haskell

On Dec 18, 2007 1:00 PM, Cristian Baboi
This is what I "understand" so far ...
Suppose we have these two values: a) \x->x + x b) \x->2 * x Because these to values are equal, all functions definable in Haskell must preserve this. This is why I am not allowed to define a function like
h :: (a->b) -> (a->b) h x = x
Of course you can define h. This is just a more specific (as far as types go) version of 'id', as defined in the Prelude: id :: a -> a id x = x where 'a' can be any type, including a function such as (a -> b). You can apply 'id' to either of your functions above, and get back an equivalent function, so each of the following evaluates to 20: let f = id (\x -> x+x) in f 10 let f = id (\x -> 2 * x) in f 10

Extensionality says that the only observable properties of functions
are the outputs they give for particular inputs. Accepting
extensionality as a Good Thing implies that enabling the user to
define a function that can differentiate between f x = x + x and g x =
2 * x is a Bad Thing.
Note that your h does not differentiate between f and g (in fact, it
does not investigate them at all), the only thing you can do with f,
g, (h f), and (g f) is apply them. Accordingly, it's a fine Haskell
definition.
"Why is extensionality a good thing?" might be a more enlightening
question. My answer would quickly be outshone by others', so I'll stop
here.
On Dec 18, 2007 3:00 PM, Cristian Baboi
This is what I "understand" so far ...
Suppose we have these two values: a) \x->x + x b) \x->2 * x Because these to values are equal, all functions definable in Haskell must preserve this. This is why I am not allowed to define a function like
h :: (a->b) -> (a->b) h x = x
The reasons are very complicated, but it goes something like this:
- when one put \x->x+x trough the function h, the compiler might change it to \x -> 2*x - when one put \x->2*x trough the function h, the compiler might change it to \x -> x + x
And we all know that \x -> 2*x is not the same as \x->x+x and this is the reason one cannot define h in Haskell _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Nicolas Frisby writes:
Extensionality says that the only observable properties of functions are the outputs they give for particular inputs. Accepting extensionality as a Good Thing implies that enabling the user to define a function that can differentiate between f x = x + x and g x = 2 * x is a Bad Thing.
Provided you subsume what you subsume, in general case there is no reason that the "standard math" equality x+x == 2*x be true. You may write whatever Num instances (for some data "x") please you. Your multiplication may have nothing to do with the addition, and your fromInteger function may do horrible things. In any case, confusing math and Haskell is not safe. Jerzy Karczmarczuk

Cristian Baboi wrote:
This is what I "understand" so far ...
Suppose we have these two values: a) \x->x + x b) \x->2 * x Because these to values are equal, all functions definable in Haskell must preserve this.
Oh but you can distinguish these functions. Consider
a x = x+x b x = 2*x
data T = A | B deriving (Show, Eq)
instance Num T where _ + _ = A _ * _ = B
f :: (T -> T) -> T f y = y undefined
main = print (f a) >> print (f b)
which prints A, then B. The key point here is that a and b have type (Num a => a -> a) and while well behaved Num instances certainly can not distinguish a and b, artificial ones like above can. Enjoy, Bertram

This is a fine warning you both point out, but I would suggest that it
distracts from the OP's question.
The previous, germane discussion holds if we assume that i) both f and
g have type Integer -> Integer, ii) the compiler writer is not out to
get us, and iii) the GMP library, if used by that compiler, is
correct. Oh and also that the representations of the Integers involved
do not require more memory than the user's computer has to offer.
Anything else seem relevant?
I do apologize for my noise if the OP was indeed thinking of + and *
as unlawful methods of the Num typeclass. A nice property of Haskell
is to note that a little confusion of math and Haskell can be very
helpful to clear up some existing confusion about Haskell.
On Dec 18, 2007 3:31 PM, Bertram Felgenhauer
Cristian Baboi wrote:
This is what I "understand" so far ...
Suppose we have these two values: a) \x->x + x b) \x->2 * x Because these to values are equal, all functions definable in Haskell must preserve this.
Oh but you can distinguish these functions. Consider
a x = x+x b x = 2*x
data T = A | B deriving (Show, Eq)
instance Num T where _ + _ = A _ * _ = B
f :: (T -> T) -> T f y = y undefined
main = print (f a) >> print (f b)
which prints A, then B.
The key point here is that a and b have type (Num a => a -> a) and while well behaved Num instances certainly can not distinguish a and b, artificial ones like above can.
Enjoy,
Bertram
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
Bertram Felgenhauer
-
Cristian Baboi
-
jerzy.karczmarczuk@info.unicaen.fr
-
Nicolas Frisby
-
Philip Weaver