The purpose of self-regulation ghci

I was learning the new Haskell today when I tried something in ghci. It basically came down to the following:

Prelude> let x = 6 Prelude> x 6 Prelude> let y = show x Prelude> y "6" Prelude> let x = show x Prelude> x "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" --(repeats) 

So can ghci not be self-imposing in a task? It seems to me that this is similar to i = i++; in C, or trying to refer to previous let (not let* ) assignments in a Schema. In any case, should I just use let y = show x ?

+6
source share
4 answers

Haskell definitions are recursive by default. So the definition you made for x refers to the same x , which is the reason for the very long string you see, because x is defined as String , which is the result of calling show by itself, so you continue to see open quotes for displaying the string, and then the quotation marks that open, etc.

These definitions can be surprisingly useful. For example, if you write:

 let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) 

you can define the Fibonacci sequence in terms of yourself as an infinite list.

Then you can do something like take 10 fibs to just see the first 10 elements.

+9
source

He really refers! He is trying to solve the equation

 x = show x 

Since show returns a string, Haskell knows that x starts with "\"" , and this is enough to guess the second character, which is enough for the third, which is enough for the fourth ...

And so on.

+5
source

Yes, you can do a self-service assignment in ghci, although this is a bit cumbersome:

 let x = 5 x <- return $ show x 

let are recursive and monadic bindings are not.

+2
source

Again: yes, Haskell can be very self-determining in the task, otherwise it will just give an error instead of printing something that cannot be analyzed, can it?

What you cannot do in Haskell ever changes / reassigns a value to a variable. It just can't be said: if you once defined x as some value, x keep that value forever. The assumption is baked in the language itself and is used for a lot of use by the compiler for many optimizations, etc.

Now you are wondering why you can write let x = ... in general, am I not saying that this is impossible? The fact is that what you do there defines a new variable, which also has the name x , but that does not change anything about the old variable with the same name. You can expect it

 Prelude> let x = 6 Prelude> let p = print x Prelude> let x = 7 Prelude> p 

to get 7 , but it actually prints 6 because p is still referring to the old variable x , and not to the new one, which was only defined later.

Still confused? Perhaps less strange is something like

 n :: Int n = 7 f :: IO () f = print $ replicate n "ha" ... -- much later, you've forgotten there was a global `n` up there... g :: String -> String g = take n where n = 37 

It’s pretty reasonable that f will take 37 characters, not 7, and any call to f continues to repeat the line only 7 times. In the end, it’s β€œ g , where n has that meaning,” but nothing else. Now let just where written the other way around. In particular, the do notation or your GHCi prompt is actually syntactic sugar for something like this:

  let x = 6 in ( print x >> ( let y = show x in ( print y >> ( let x = show x in ( print x ) ) ) ) 

Each paragraph covers scope. Variables defined in external areas can be used, but local ones are preferred if found. So, let x = show x in ( print x ) can be considered by itself, the original x = 6 is hidden out of scope here. Therefore, the only way to define a definition is to refer to itself recursively.

+1
source

All Articles