* <hask>trace</hask> requires a rather strict scheme: the function it takes as an argument must be exactly of the same scheme as seen in the above feedback picture

+

* the recursion by which we can solve the problem eventually (here: math>\mathrm{scale}\Vert\mathrm{norm}^2</math>) usually provides another scheme. E.g. here we cannot compute norm directly by recursion.

+

So we have to join together the needs of <hask>trace</hask> and the possibilities of recursion together,

+

we have to convert between these two plugs if they are incompatible,

+

that is why we created

+

<math>\mathrm{divide}\Vert\mathrm{norm}</math>.

+

+

This is not the only way to force the problem to the shape of <hask>trace</hask>.

but this is divergent (even for the empty list): it does not terminate at all, albeit this solution seemed for me standing in a duality relation with the previous one.

+

+

Excuse me for my toys.

+

Of course in Wouter Swiestra's [http://www.haskell.org/tmrwiki/WhyAttributeGrammarsMatter Why Attribute Grammars Matter] there are much deeper solutions to this and other examples.

+

And also very deep connections with

+

* catamorhisms, category theory

+

* attribute grammars

+

are described there.

+

And there are links from that article to other materials providing deep insights in these powerful theories: attribute grammar tools and articles of the Essential Haskell Compiler project.

+

+

It is no wonder that it is exactly a compiler project homepage that provides good circular programming and attribute grammar tutorials

+

* both on its [http://www.cs.uu.nl/wiki/Ehc/WebHome project page]

+

* and on a separate [http://www.cs.uu.nl/wiki/HUT/AttributeGrammarSystem attribute grammar] page:

+

the reason may be that a compiler project is complex enough to require good separation of concerns, modularity, reuse (goals of Aspect Oriented Programming, too), and attribute grammars are powerful tools to achieve these goals.

+

+

== Related concepts ==

+

+

See also [[Attribute grammar]] page.

[[Category:Idioms]]

[[Category:Idioms]]

Revision as of 15:04, 5 June 2006

1 Porting from HaWiki's CircularProgramming

I port only my material from there (because I know only the copyright status of my writings on HaWiki).

Notations: in
,
my -II- infix notation means parallelity,
referring to the fact that the wonderful achievement of these functions is being able to work in one traversal.
Sometimes I use -X- infix notation instead of -II-, referring to cross product:

As we can see, we have things enough to confuse: two arguments, a returned tuple, how they depend from each other...

A hint: let us think of the scheme of

trace

:

input -- what we work with

output -- what we get

feedback -- a state-like thing, yes, a feedback, that can be thought of through both aspects

feedback-as-produced: thinking of it as it leaves the box

feedback-as-fed-back: thinking of it as it is fed back into the box again

If we decide, what the roles of input, output, feedback plays, then these circular programming funtions will look easier. E.g. here, at the repmin problem

input is a tree filled with numbers, a heterogenous tree

output is the repmin'ed tree, a homogenized tree

feedback (something state-like): here that strange numeric value plays the role of feedback! Its two aspects are

feedback-as-produced -- in this aspect, it is a minimum value, a statistic of the tree

feedback-as-fed-back -- in this aspect, it is a setter value, a rather seed-like thing: it is spred homogenously in the shape of a given tree

Now it is easier to look at
, we have a road-map for our eyes in the jungle of parameters and returned tuple.

requires a rather strict scheme: the function it takes as an argument must be exactly of the same scheme as seen in the above feedback picture

the recursion by which we can solve the problem eventually (here: math>\mathrm{scale}\Vert\mathrm{norm}^2</math>) usually provides another scheme. E.g. here we cannot compute norm directly by recursion.

So we have to join together the needs of

trace

and the possibilities of recursion together,

we have to convert between these two plugs if they are incompatible,
that is why we created
.

This is not the only way to force the problem to the shape of

trace

.

There are other ways, but they do not seem so natural,
they look somewhat artificial,
albeit in efficiency aspects, I think, they are the same:

this is good, too. All these three solutions converge, they terminate.

But there are circular programming examples
where such possible solutions will not be so equivalent:
one of them may diverge, while the other converge.
It seems to me, the diff example (described in Wouter Swiestra's Why Attribute Grammars Matter) is exactly such circular programming problem.

This diff example is:

how to compute the average of a list

and (in the same traversal of the list) decrease all elements of the list by this average value.

As we can see, recursion cannot deal with average (indirectly), that is why
provides (besides the list with all its element decremented by the delta value) not an average value, but a length---sum pair.

There is no real reason, why the return value of

should be

([a],(a,Integer))

instead of the more simple

([a], a,Integer)

:

let us untangle the nested tuples, using the
law!
Let us use a
instead of
:

but this is divergent (even for the empty list): it does not terminate at all, albeit this solution seemed for me standing in a duality relation with the previous one.

Excuse me for my toys.
Of course in Wouter Swiestra's Why Attribute Grammars Matter there are much deeper solutions to this and other examples.
And also very deep connections with

catamorhisms, category theory

attribute grammars

are described there.
And there are links from that article to other materials providing deep insights in these powerful theories: attribute grammar tools and articles of the Essential Haskell Compiler project.

It is no wonder that it is exactly a compiler project homepage that provides good circular programming and attribute grammar tutorials

the reason may be that a compiler project is complex enough to require good separation of concerns, modularity, reuse (goals of Aspect Oriented Programming, too), and attribute grammars are powerful tools to achieve these goals.