Using a character before defining it

As it appears in the line below on the right side of the equation, you can use the "fibs" symbol, although it is not yet defined:

let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) 
+6
source share
4 answers

The fact is that the definition of fibs

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

not evaluated until it is used elsewhere. Then the definition is expanded using the already known part. Let's start with fibs = 0 : 1 : ??? . Then, if the third element is ever needed, the definition is evaluated one more step,

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

but then the unknown part ??? became partially known, it was defined as ??? = 1 : ???? ??? = 1 : ???? , so the deployment can continue,

  = 0 : 1 : 1 : zipWith (+) (1 : 1 : ????) (1 : ????) = 0 : 1 : 1 : 2 : zipWith (+) (1 : ????) (????) -- now ???? is known to be 2:????? = 0 : 1 : 1 : 2 : zipWith (+) (1 : 2 : ?????) (2 : ?????) 

and etc.

+19
source

In fact, it will not try to call fibs in your definition until something else uses fibs later in your program, after which fibs fully defined.

You can do this in most other languages:

 int foo(int x) { if (x <= 0) return 0; // will call foo when it gets there, at which point its been defined foo(x - 1); } 
+6
source

All Haskell bindings are recursive. This is different from most languages, but often works correctly due to laziness (Haskell's assessment is not strict, unlike most popular languages). Beginners often get confused when they try something like:

 main = do let a = 3 let a = 3 + a print a 

Since the second binding to a actually ignores and obscures the first and defines a in terms of itself, which causes an infinite loop when you try to print the result 3 + 3 + 3 + 3 + ...

A simple example of an infinite list is ones : infinite list 1 s

 ones = 1 : ones 

In this case, they simply refer to themselves

  _______ | | v | ________ | | ones | | | 1 : ---| -------- 

In Haskell, you can create an infinite tree in much the same way you can create an infinite list:

 data Tree a = Stub | Branch a (Tree a) (Tree a) onesTree = Branch 1 onesTree onesTree ______ _______ | | | | | vv | | ____________ | | | onesTree | | |--- | 1 | ----| ------------ 

I think the real question is: why don't other languages โ€‹โ€‹support recursive values โ€‹โ€‹as conveniently as Haskell?

+4
source

Itโ€™s good to understand this, itโ€™s good to understand how lazy assessment is performed. Basically, unvalued expressions are represented by thunks : a data structure that represents all the information needed to calculate a value when it is really needed. When the latter happens (or, as we say, when thunk is forced ), the code to compute the value is executed, and the contents of thunk are replaced by a result that may have pointers to other thunks.

So fibs starts like thunk. This thunk contains pointers to the code that was used to calculate its value, and pointers to the thunks that this code takes as arguments. One of these last pointers is a pointer to fibs .

+1
source

Source: https://habr.com/ru/post/911618/


All Articles