Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "error" function prints Exception many times

Tags:

haskell

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.

like image 597
A Monad is a Monoid Avatar asked Aug 02 '26 16:08

A Monad is a Monoid


2 Answers

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.

like image 128
Willem Van Onsem Avatar answered Aug 05 '26 14:08

Willem Van Onsem


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
...
like image 23
Federico Sawady Avatar answered Aug 05 '26 13:08

Federico Sawady



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!