Ok, but you didn't, really. You gave an implementation difference between the two, but what is the conceptual difference?
Also, the implementation difference is just, well, an implementation detail. If you need to worry about whether a value requires calculation or not, you are likely about to mess things up anyway. Consider the following:
f = (a long calculation of some sort)
main = do
doStuffWith f
doMoreStuffWith f
The compiler may or may not decide that the result of f should be cached, meaning that after the first evaluation of f, f will from then on be a plain value thunk.
Given that evaluation order in Haskell is complex (and something you should try to avoid thinking about as much as possible), this distinction does not make conceptual sense.
Further down in my program listing, there is:
bob = f
Is bob a value, because it takes no parameter? Is it a function because f happens to be a function? Is it really a function but practically a value since f has already been evaluated? Is f so trivial (5 + 2) that its result has already been evaluated and inlined by the compiler?
These questions can be answered, but they shouldn't. Their answers are not obvious from the code, and also subject to compiler decisions.
Therefore, "f = sum [1,2,3,4,5,6]" and "f = 21" are completely conceptually equal. The distinction is not important when you are programming. It may be important from a performance perspective in some instances, but that is usually a sign that you should defer some code to C.
> Is bob a value, because it takes no parameter? Is it a function because f happens to be a function?
Functions are values. But not all values are functions. Functions are values with abstract type a -> a. That's what a function is in Haskell. (Of course, I'm only talking about functions from values to values here, not about functions from types to types and so on.)
Whether bob is a function or not will of course depend on its type. For instance, consider the following definition for f:
f = (+ 5)
Then yes, bob will be a function, with type Num a => a -> a. On the other hand, if you decide to define f as
f = take (10^10) $ [1..]
then it won't. The distinction here is determined entirely at compile time: it's about what type a particular value has.
> Therefore, "f = sum [1,2,3,4,5,6]" and "f = 21" are completely conceptually equal.
Right. They're both values of some concrete integer type.
If you were to act like doubles are (optimized) thunks, would that ever trip you up? Haskell's strictness means that its abstractions don't leak as much. If I'm able to pretend that everything is a function, and doing so won't lead me astray, I don't see the point of caring that some things are really values (for some definition of real). That seems like the sort of detail that Haskell makes a point of protecting you from.
Don't forget currying. Actually, in Haskell, function have exactly one argument. If you need more, just return a function.
-- appears to have 2 arguments
foo :: Int -> Int -> Int
foo x y = x + (y * y)
-- equivalent definition
foo :: Int -> (Int -> Int)
foo x = \y -> x + (y * y)
-- or even more consistently
foo :: Int -> (Int -> Int)
foo = \x -> (\y -> x + (y * y))
Thinking this way is more useful in the long run: it makes partial application more natural.
bar :: Int -> List Int -> List Int
Bar = map (foo 42)