-1

I am confused about when Haskell evaluates functions, compared to when it just returns the function itself. I was taught that pattern matching drives function evaluation, but then I don't understand why

f :: Int -> Int
f x = x+1

works. Does f add 1 to an integer, or does it return a function which adds 1 to an integer? Are these two the same thing? There is no pattern matching as far as I can tell, so I'm not sure why it gets evaluated.

Another question: suppose I want to make an 8x8 list that contains all 0's, except the first row contains the numbers 1,2,3,4,5,6,7,8 instead. Is there any way I could initialize it to all 0's first and then change the first row to [1..8]? I understand that it's not idiomatic to make sequential code like this, so is there a better way to do it, hopefully without using do blocks?

Finally, I am also confused about the let and where syntax. Suppose that in the middle of a function definition, I say temp = x + 1. How is this different from saying let temp = x + 1 or ...temp where temp = x + 1? In each of these cases, does temp have type Int or Int -> Int? Why do people use do with let so often?

Agent 008
  • 141
  • 8
  • I don't understand what you mean by "evaluate functions" and "return functions". – melpomene Sep 21 '19 at 13:21
  • 6
    This seems like 3 completely different questions - some of them (the first, in particular) too vaguely stated to really be able to answer. It is fine to have several different questions, but please create a new question for each, rather than putting unrelated queries into one question. – Robin Zigmond Sep 21 '19 at 13:21
  • 1
    "*Suppose that in the middle of a function definition, I say `temp = x + 1`.*" That's a syntax error. – melpomene Sep 21 '19 at 13:22
  • In Haskell all variables are immutable. `f` can not increment a variable. `f` simply returns a `x+1`. – Willem Van Onsem Sep 21 '19 at 13:22

1 Answers1

0

This certainly was a collection of questions.

Firstly, about evaluation, Haskell is lazy. It will evaluate values as they are needed. This includes the fact that a function is not necessarily evaluated in its entirety. Pattern matching may drive evaluation in some cases, for instance in maybe either a Nothing or Just x must match, in order to find out what value is produced. But if you didn't demand the result in the first place, this matching was never needed.

f in your example is a function known as (+1), or more explicitly \x -> x + 1. Being a function, it must be applied to a value to produce another, and there is in fact a pattern; the argument x, having type Int. This works as a simple binding, but it could have been a constant value pattern like 1 instead. Here's an example:

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

The two first patterns give us our base cases.

An 8x8 grid of numbers is a matrix, not a list. Data.Array, Data.Matrix and Data.Vector provide types that can describe such things more accurately, and what you describe can be done. Data.Ix provides multidimensional indices and functions like Data.Vector.modify may perform updates in place without violating value immutability.

let bindings in expression and expression where bindings are mostly a matter of preference. let binding within a do block is a different matter. In your sample binding temp = x + 1, x must be bound from elsewhere, + is of type Num a => a -> a -> a, so both x and temp must be the same Num a. A function must take an argument, so this is just a value (though mathematically it's a function of x).

As for do with let, it's essentially a shorthand for adding another binding; you could write:

main = do
    putStrLn "hello"
    let word = "world"
    putStrLn word

and it's equivalent to:

main = do
    putStrLn "hello"
    let word = "world" in do
        putStrLn word

This provides a way to introduce a pure value mid-do, like <- introduces monadic ones.

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
  • Please don't spread the dangerous misconception that `succ` is always the same as `(+1)` when both are available. They're different for [`Fixed`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Fixed.html#t:Fixed), for example, and the assumption that they're always the same causes [real problems](https://stackoverflow.com/q/57843502/7509065). – Joseph Sible-Reinstate Monica Sep 21 '19 at 16:51
  • 1
    Ah, you're right! succ would give you the next possible value while +1 would increment by one unit. – Yann Vernier Sep 21 '19 at 18:29