Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this implementation of `init` work?

I'm learning Haskell and I found an interesting implementation of init using foldr. However, I have difficulty understanding how it works.

init' xs = foldr f (const []) xs id
    where f x g h = h $ g (x:)

Consider I have an input of [1,2,3], then is would become

f 1 (f 2 ( f 3 (const []))) id

I substitute those parameters into f and the innermost one becomes h $ (const []) (1:), which is simply h []. However, when I want to reduce the expression further, I find it hard to grasp. The next one becomes f 2 (h []) , which is

h $ (h []) (2:)

if it works like that. This looks confusing to me. To match the type of foldr, h should be of type [a] -> [a] and h [] would just be of type [a], which isn't applicable to (2:).

I also thought about it in another way, that f x g returns a function of type ([a] -> [a]) -> [a], this kinda makes sense considering applying id afterwards. But then I realized I still don't know what this h is doing here. It looks like h conveys g (x:) from last time into the next application.

Did I miss something when I think about doing fold with function as accumulator?

I'd really appreciate if anyone could help me with this.

like image 946
Emmanuel Avatar asked Aug 07 '20 23:08

Emmanuel


People also ask

How does Init method work?

__init__ method It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.

How does init work in Python?

The __init__ method is the Python equivalent of the C++ constructor in an object-oriented approach. The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.

What does def __ init __( self do?

__init__ does act like a constructor. You'll need to pass "self" to any class functions as the first argument if you want them to behave as non-static methods. "self" are instance variables for your class. 'self' defines if a method is static or not!

What is init used for?

What is __init__ in Python? The Default __init__ Constructor in C++ and Java. Constructors are used to initializing the object's state. The task of constructors is to initialize(assign values) to the data members of the class when an object of the class is created.


1 Answers

For a list [1,2,3], the init' is substituted by:

init' [1,2,3]
  = foldr f (const []) [1,2,3] id
  = f 1 (foldr f (const []) [2,3]) id

Here f is thus called with 1 as x, foldr f (const []) [2,3] as g and id h, this thus means that the this is resolved to:

id (foldr f (const []) [2,3] (1:))

It thus means that instead of using id in the recursion, we now will prepend 1: to the result. Next we can resolve the inner foldr to:

foldr f (const []) [2,3] (1:)
 = f 2 (foldr f (const []) [3]) (1:)
 = (1:) (foldr f (const []) [3] (2:))

The inner foldr then results in:

foldr f (const []) [3] (2:)
 = f 3 (foldr f (const []) []) (2:)
 = (2:) (foldr f (const []) [] (3:))

finally the foldr f (const []) [] will resulve to const [].

This thus means that:

foldr f (const []) [3] (2:)
 = f 3 (foldr f (const []) []) (2:)
 = (2:) (foldr f (const []) [] (3:))
 = (2:) (const [] (3:))

The const will thus ignore the argument (3:), and return an empty list. So the result of foldr f (const []) [3] (2:) is [2]:

foldr f (const []) [3] (2:)
 = f 3 (foldr f (const []) []) (2:)
 = (2:) (foldr f (const []) [] (3:))
 = (2:) (const [] (3:))
 = (2:) []
 = [2]

If we substitute this in the foldr f (const []) [2,3] (1:), we get:

foldr f (const []) [2,3] (1:)
 = f 2 (foldr f (const []) [3]) (1:)
 = (1:) (foldr f (const []) [3] (2:))
 = (1:) [2]
 = [1,2]

so that means that init' [1,2,3] will return [1,2].

This thus means that a

foldr f (const []) [x1, x2, …, xn] (x0:)

will be replaced by:

(x0:) (foldr f (const []) [x2, x3, …, xn] (x1:))

If the list gets exhausted, then it will replace:

foldr f (const []) [] (xn:)

with:

const [] (xn:)

so the last element will be ignored by the const function.

like image 108
Willem Van Onsem Avatar answered Oct 17 '22 02:10

Willem Van Onsem