2

I was wondering why error function returns this in ghci:

First with one call:

Prelude> error ""
*** Exception: 
CallStack (from HasCallStack):
  error, called at <interactive>:3:1 in interactive:Ghci1

Then with two:

Prelude> error (error "")
*** Exception: *** Exception: 
CallStack (from HasCallStack):
  error, called at <interactive>:2:8 in interactive:Ghci1

And with three and so on:

Prelude> error (error ( error ""))
*** Exception: *** Exception: *** Exception: 
CallStack (from HasCallStack):
  error, called at <interactive>:1:16 in interactive:Ghci1

Why there are many "*** Exception:" printed as error stacked?

I made this function that recieves a number and print exception that amount of times too:

printException n = foldr (\c r -> c error r) id (replicate n (.)) ""

But I was wondering also why

until (const False) error ""

Does not print Exception indefinitely.

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
  • 1
    You might also like to read answers to [one of my questions from a few years back](https://stackoverflow.com/q/11070690/791604). – Daniel Wagner Apr 21 '23 at 14:35

3 Answers3

5

You have an error in the message of the error. Due to laziness when it prints the outer error, it raises the inner one which will print a second one.

It thus will start printing the message:

*** Exception: …

but then it starts the putStrLn of the message. Note that this message was not yet evaluated. Indeed, Haskell is lazy, it will thus only evaluate the message if it is going to print it, so now a second error is raised, and so it starts printing the second message.

But I was wondering also why

until (const False) error ""

Does not print the exception indefinitely.

Here it starts printing the string, but it never will generate anything. Indeed, it will produce an expression that looks like error (error (error (… (error "") …))), but it will never evaluate any error, not even the outer one, since it keeps busy constructing a gigantic expression tree.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
2

Let e be any expression of type String. Then, error e raises an exception, which (in normal conditions) prints *** Exception: followed by the string e.

Hence, e is now being evaluated (not any earlier!). That might involve evaluating another error e', which would print another *** Exception: followed by e'.

And so on.

The key point here is that e is evaluated lazily, only when it is being printed, so we observe *** Exception: in front of it.

For the last question, note that until (const False) f x will never evaluate any f (f (f ... (f x)). This is because, by laziness, const False x, const False (f x), const False (f (f x)), ... do not need to evaluate x, nor f x, nor f (f x), ...

Hence, in your example error is never really called.

chi
  • 111,837
  • 3
  • 133
  • 218
2

error is lazy and the String is evaluated lazily as well. Also, since error :: String -> a, the result of error can be the input of the function error. And strings also are printed lazily, char by char.

Maybe to understand more the situation, you can think, for example, in a function like this:

errorsFrom n = error (show n ++ "\n" ++ errorsFrom (n+1))

Then evaluate on the console errorsFrom 0, and you will see this:

*** Exception: 0
*** Exception: 1
*** Exception: 2
*** Exception: 3
*** Exception: 4
*** Exception: 5
*** Exception: 6
*** Exception: 7
*** Exception: 8
*** Exception: 9
*** Exception: 10
...
Federico Sawady
  • 900
  • 5
  • 12