|
310 | 310 | "Extension to subtraction",
|
311 | 311 | "Fixpoint operator.",
|
312 | 312 | "Extension to multiplication",
|
313 |
| -"Mixing it all together" |
| 313 | +"Mixing it all together", |
| 314 | +"Open/Closed Principle", |
| 315 | +"Issues with polymorphic variants", |
| 316 | +"Multivariant Open Recursion" |
314 | 317 | ];
|
315 | 318 | function expand_all(dummy)
|
316 | 319 | {
|
|
377 | 380 | <div class=m2><a href="#Extension_to_multiplication_h">Extension to multiplication</a></div>
|
378 | 381 | <div class=m2><a href="#Mixing_it_all_together_h">Mixing it all together</a></div>
|
379 | 382 | </div>
|
380 |
| - <script>counter_max=1;</script> |
| 383 | + <div class=m1 onclick="mshow('menu2','#Open/Closed Principle_h')"> <a href="#Open/Closed_Principle_h">Open/Closed Principle</a></div> |
| 384 | + <div class=sm id=menu2> |
| 385 | + <div class=m2><a href="#Issues_with_polymorphic_variants_h">Issues with polymorphic variants</a></div> |
| 386 | + <div class=m2><a href="#Multivariant_Open_Recursion_h">Multivariant Open Recursion</a></div> |
| 387 | + </div> |
| 388 | + <script>counter_max=2;</script> |
381 | 389 | </div>
|
382 | 390 | <!--End Left Margin Toc-->
|
383 | 391 |
|
|
429 | 437 | <span class="lineno" id=line3></span> `Add of adde * adde
|
430 | 438 | <span class="lineno" id=line4></span> );
|
431 | 439 | </pre></p><p>Notice, it is a recursive data type. The function we want is
|
432 |
| -</p><p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> eval (term: adde) => |
| 440 | +</p><p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> evala (term: adde) => |
433 | 441 | <span class="lineno" id=line2></span> <span class="small_keyword" title="match statement or expression">match</span> term <span class="small_keyword" title="type-class constraint">with</span>
|
434 | 442 | <span class="lineno" id=line3></span> | `Int j => j
|
435 |
| -<span class="lineno" id=line4></span> | `Add (a,b) => eval a + eval b |
| 443 | +<span class="lineno" id=line4></span> | `Add (a,b) => evala a + evala b |
436 | 444 | <span class="lineno" id=line5></span> <span class="small_keyword" title="end a match statement or expression">endmatch</span>
|
437 | 445 | <span class="lineno" id=line6></span> ;
|
438 | 446 | </pre></p><p>Again notice it is a recursive function. We are going to recode
|
|
449 | 457 | </p><p>And here's the open version of the function:
|
450 | 458 | </p><pre class='inclusion'>
|
451 | 459 | examples/openrecursion/openrec.flx</pre>
|
452 |
| -<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_eval[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_adde[T]) => |
| 460 | +<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_evala[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_adde[T]) => |
453 | 461 | <span class="lineno" id=line2></span> <span class="small_keyword" title="match statement or expression">match</span> term <span class="small_keyword" title="type-class constraint">with</span>
|
454 | 462 | <span class="lineno" id=line3></span> | `Int j => j
|
455 | 463 | <span class="lineno" id=line4></span> | `Add (a,b) => eval a + eval b
|
|
461 | 469 | </p><pre class='inclusion'>
|
462 | 470 | examples/openrecursion/openrec.flx</pre>
|
463 | 471 | <p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define an alias for a type expression">typedef</span> adde = o_adde[adde];
|
464 |
| -<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> eval (term:adde):<span class="library" title="binding of C int type">int</span> => o_eval[adde] eval term; |
| 472 | +<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> evala (term:adde):<span class="library" title="binding of C int type">int</span> => o_evala[adde] evala term; |
465 | 473 | </pre></p><p>What we have done is close the open data type by
|
466 | 474 | replacing the type variable with a self-reference.
|
467 | 475 | Similarly, we have closed the function, by replacing
|
|
471 | 479 | </p><p>Here is a test case:
|
472 | 480 | </p><pre class='inclusion'>
|
473 | 481 | examples/openrecursion/openrec.flx</pre>
|
474 |
| -<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a mutable variable">var</span> x : adde = `Add (`Add (`Int 39, `Int 2), `Int 1); |
475 |
| -<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a mutable variable">var</span> y = eval x; |
476 |
| -<span class="lineno" id=line3></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y; |
| 482 | +<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a mutable variable">var</span> xa : adde = `Add (`Add (`Int 39, `Int 2), `Int 1); |
| 483 | +<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a mutable variable">var</span> yaa = evala xa; |
| 484 | +<span class="lineno" id=line3></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ya="</span>+yaa.<span class="library" title="Convert a value to a string">str</span>; |
477 | 485 | </pre></p></div><h2 id='Extension_to_subtraction_h'><img src='/share/src/web/images/minus.gif' id='Extension to subtraction' onclick='toggle(this,"Extension_to_subtraction_d")' alt='+'/> 1.2 Extension to subtraction</h2><div id='Extension_to_subtraction_d' style='display:block'>
|
478 | 486 | <p>Now we're going to add a new feature: subtraction.
|
479 | 487 | </p><p>Here is the open version of the type and evaluator:
|
|
483 | 491 | <span class="lineno" id=line2></span> | o_adde[T]
|
484 | 492 | <span class="lineno" id=line3></span> | `Sub of T * T
|
485 | 493 | <span class="lineno" id=line4></span> );
|
486 |
| -<span class="lineno" id=line5></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_eval2[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_sube[T]):<span class="library" title="binding of C int type">int</span> => |
| 494 | +<span class="lineno" id=line5></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_evals[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_sube[T]):<span class="library" title="binding of C int type">int</span> => |
487 | 495 | <span class="lineno" id=line6></span> <span class="small_keyword" title="match statement or expression">match</span> term <span class="small_keyword" title="type-class constraint">with</span>
|
488 | 496 | <span class="lineno" id=line7></span> | `Sub (a,b) => eval a - eval b
|
489 |
| -<span class="lineno" id=line8></span> | o_adde[T] :>> k => o_eval eval k |
| 497 | +<span class="lineno" id=line8></span> | o_adde[T] :>> k => o_evala eval k |
490 | 498 | <span class="lineno" id=line9></span> <span class="small_keyword" title="end a match statement or expression">endmatch</span>
|
491 | 499 | <span class="lineno" id=line10></span> ;
|
492 | 500 | </pre></p><p>Notice both the type and function delegate to the existing code for addition
|
493 | 501 | and only add support for our new operation, subtraction.
|
494 | 502 | </p></div><h2 id='Fixpoint_operator._h'><img src='/share/src/web/images/minus.gif' id='Fixpoint operator.' onclick='toggle(this,"Fixpoint_operator._d")' alt='+'/> 1.3 Fixpoint operator.</h2><div id='Fixpoint_operator._d' style='display:block'>
|
495 |
| -<p>The closure of the the open type and function ic called <em>fixating</em> them. |
| 503 | +<p>The closure of the the open type and function is called <em>fixating</em> them. |
496 | 504 | What we have done is to manually introduce the self-reference.
|
497 | 505 | For the data type, we used a self-refering type alias; for the function
|
498 | 506 | we used eta-expansion.
|
|
503 | 511 | examples/openrecursion/openrec.flx</pre>
|
504 | 512 | <p><pre class='flxbg'><span class="lineno" id=line1></span> typefun o_sube_f (T:TYPE) : TYPE => o_sube[T];
|
505 | 513 | <span class="lineno" id=line2></span> <span class="big_keyword" title="Define an alias for a type expression">typedef</span> sube = tfix<TYPE> o_sube_f;
|
506 |
| -<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> eval2 (term:sube):<span class="library" title="binding of C int type">int</span> => (fix[sube,<span class="library" title="binding of C int type">int</span>] o_eval2[sube]) term; |
| 514 | +<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> evals (term:sube):<span class="library" title="binding of C int type">int</span> => (fix[sube,<span class="library" title="binding of C int type">int</span>] o_evals[sube]) term; |
507 | 515 | </pre></p><p>Here are the definitions from the standard library:
|
508 | 516 | </p><p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> fix[D,C] (f:(D->C)->D->C) (x:D) : C => f (fix f) x;
|
509 | 517 | <span class="lineno" id=line2></span> typefun tfix<K> (f: K ->K):K => f x as x:K;
|
|
516 | 524 | </p><p>Finally a test case:
|
517 | 525 | </p><pre class='inclusion'>
|
518 | 526 | examples/openrecursion/openrec.flx</pre>
|
519 |
| -<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a mutable variable">var</span> x2 : sube = `Add (`Sub (`Int 39, `Int 2), `Int 1); |
520 |
| -<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a mutable variable">var</span> y2 = eval2 x2; |
521 |
| -<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a mutable variable">var</span> y3 = eval2 x; <span class="comment">// ORGINAL DATA</span> |
522 |
| -<span class="lineno" id=line4></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y2; |
523 |
| -<span class="lineno" id=line5></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y3; |
| 527 | +<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a mutable variable">var</span> xs : sube = `Add (`Sub (`Int 39, `Int 2), `Int 1); |
| 528 | +<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a mutable variable">var</span> yss = evals xs; |
| 529 | +<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a mutable variable">var</span> ysa = evals xa; <span class="comment">// ORGINAL DATA</span> |
| 530 | +<span class="lineno" id=line4></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ys="</span>+yss.<span class="library" title="Convert a value to a string">str</span>; |
| 531 | +<span class="lineno" id=line5></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ya="</span>+ysa.<span class="library" title="Convert a value to a string">str</span>; |
524 | 532 | </pre></p><p>It's very important to notice that the original data also works with
|
525 | 533 | the new function! Of course it's obvious why: the function <code>sube</code>
|
526 | 534 | delegates to <code>adde</code> in that case.
|
|
540 | 548 | <span class="lineno" id=line2></span> | o_adde[T]
|
541 | 549 | <span class="lineno" id=line3></span> | `Mul of T * T
|
542 | 550 | <span class="lineno" id=line4></span> );
|
543 |
| -<span class="lineno" id=line5></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_eval3[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_mule[T]):<span class="library" title="binding of C int type">int</span> => |
| 551 | +<span class="lineno" id=line5></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_evalm[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_mule[T]):<span class="library" title="binding of C int type">int</span> => |
544 | 552 | <span class="lineno" id=line6></span> <span class="small_keyword" title="match statement or expression">match</span> term <span class="small_keyword" title="type-class constraint">with</span>
|
545 | 553 | <span class="lineno" id=line7></span> | `Mul(a,b) => eval a * eval b
|
546 |
| -<span class="lineno" id=line8></span> | o_adde[T] :>> k => o_eval eval k |
| 554 | +<span class="lineno" id=line8></span> | o_adde[T] :>> k => o_evala eval k |
547 | 555 | <span class="lineno" id=line9></span> <span class="small_keyword" title="end a match statement or expression">endmatch</span>
|
548 | 556 | <span class="lineno" id=line10></span> ;
|
549 | 557 | <span class="lineno" id=line11></span> typefun o_mule_f (T:TYPE) : TYPE => o_mule[T];
|
550 | 558 | <span class="lineno" id=line12></span> <span class="big_keyword" title="Define an alias for a type expression">typedef</span> mule = tfix<TYPE> o_mule_f;
|
551 |
| -<span class="lineno" id=line13></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> eval3 (term:mule):<span class="library" title="binding of C int type">int</span> => (fix[mule,<span class="library" title="binding of C int type">int</span>] o_eval3[mule]) term; |
552 |
| -<span class="lineno" id=line14></span> <span class="big_keyword" title="Define a mutable variable">var</span> x3 : mule = `Add (`Mul(`Int 39, `Int 2), `Int 1); |
553 |
| -<span class="lineno" id=line15></span> <span class="big_keyword" title="Define a mutable variable">var</span> y4 = eval3 x3; |
554 |
| -<span class="lineno" id=line16></span> <span class="big_keyword" title="Define a mutable variable">var</span> y5 = eval3 x; <span class="comment">// ORGINAL DATA</span> |
555 |
| -<span class="lineno" id=line17></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y4; |
556 |
| -<span class="lineno" id=line18></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y5; |
| 559 | +<span class="lineno" id=line13></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> evalm (term:mule):<span class="library" title="binding of C int type">int</span> => (fix[mule,<span class="library" title="binding of C int type">int</span>] o_evalm[mule]) term; |
| 560 | +<span class="lineno" id=line14></span> <span class="big_keyword" title="Define a mutable variable">var</span> xm : mule = `Add (`Mul(`Int 39, `Int 2), `Int 1); |
| 561 | +<span class="lineno" id=line15></span> <span class="big_keyword" title="Define a mutable variable">var</span> ymm = evalm xm; |
| 562 | +<span class="lineno" id=line16></span> <span class="big_keyword" title="Define a mutable variable">var</span> yma = evalm xa; <span class="comment">// ORGINAL DATA</span> |
| 563 | +<span class="lineno" id=line17></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ym="</span>+ymm.<span class="library" title="Convert a value to a string">str</span>; |
| 564 | +<span class="lineno" id=line18></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ya="</span>+yma.<span class="library" title="Convert a value to a string">str</span>; |
557 | 565 | </pre></p></div><h2 id='Mixing_it_all_together_h'><img src='/share/src/web/images/minus.gif' id='Mixing it all together' onclick='toggle(this,"Mixing_it_all_together_d")' alt='+'/> 1.5 Mixing it all together</h2><div id='Mixing_it_all_together_d' style='display:block'>
|
558 | 566 | <p>We're no going to mix it all together and also add division.
|
559 | 567 | </p><pre class='inclusion'>
|
|
563 | 571 | <span class="lineno" id=line3></span> | o_mule[T]
|
564 | 572 | <span class="lineno" id=line4></span> | `Div of T * T
|
565 | 573 | <span class="lineno" id=line5></span> );
|
566 |
| -<span class="lineno" id=line6></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_eval4[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_dive[T]):<span class="library" title="binding of C int type">int</span> => |
| 574 | +<span class="lineno" id=line6></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> o_evald[T] (eval: T -> <span class="library" title="binding of C int type">int</span>) (term: o_dive[T]):<span class="library" title="binding of C int type">int</span> => |
567 | 575 | <span class="lineno" id=line7></span> <span class="small_keyword" title="match statement or expression">match</span> term <span class="small_keyword" title="type-class constraint">with</span>
|
568 | 576 | <span class="lineno" id=line8></span> | `Div(a,b) => eval a / eval b
|
569 |
| -<span class="lineno" id=line9></span> | o_sube[T] :>> k => o_eval2 eval k |
570 |
| -<span class="lineno" id=line10></span> | o_mule[T] :>> k => o_eval3 eval k |
| 577 | +<span class="lineno" id=line9></span> | o_sube[T] :>> k => o_evals eval k |
| 578 | +<span class="lineno" id=line10></span> | o_mule[T] :>> k => o_evalm eval k |
571 | 579 | <span class="lineno" id=line11></span> <span class="small_keyword" title="end a match statement or expression">endmatch</span>
|
572 | 580 | <span class="lineno" id=line12></span> ;
|
573 | 581 | <span class="lineno" id=line13></span> typefun o_dive_f (T:TYPE) : TYPE => o_dive[T];
|
574 | 582 | <span class="lineno" id=line14></span> <span class="big_keyword" title="Define an alias for a type expression">typedef</span> dive = tfix<TYPE> o_dive_f;
|
575 |
| -<span class="lineno" id=line15></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> eval4 (term:dive):<span class="library" title="binding of C int type">int</span> => (fix[dive,<span class="library" title="binding of C int type">int</span>] o_eval4[dive]) term; |
576 |
| -<span class="lineno" id=line16></span> <span class="big_keyword" title="Define a mutable variable">var</span> x4 : dive = |
| 583 | +<span class="lineno" id=line15></span> <span class="big_keyword" title="Define a function with no side-effects">fun</span> evald (term:dive):<span class="library" title="binding of C int type">int</span> => (fix[dive,<span class="library" title="binding of C int type">int</span>] o_evald[dive]) term; |
| 584 | +<span class="lineno" id=line16></span> <span class="big_keyword" title="Define a mutable variable">var</span> xd : dive = |
577 | 585 | <span class="lineno" id=line17></span> `Add (
|
578 | 586 | <span class="lineno" id=line18></span> `Mul (
|
579 | 587 | <span class="lineno" id=line19></span> `Int 39,
|
|
586 | 594 | <span class="lineno" id=line26></span> `Int 66
|
587 | 595 | <span class="lineno" id=line27></span> )
|
588 | 596 | <span class="lineno" id=line28></span> ;
|
589 |
| -<span class="lineno" id=line29></span> <span class="big_keyword" title="Define a mutable variable">var</span> y6 = eval4 x4; |
590 |
| -<span class="lineno" id=line30></span> <span class="big_keyword" title="Define a mutable variable">var</span> y7 = eval4 x; <span class="comment">// ORGINAL DATA</span> |
591 |
| -<span class="lineno" id=line31></span> <span class="big_keyword" title="Define a mutable variable">var</span> y8 = eval4 x2; <span class="comment">// ORGINAL DATA</span> |
592 |
| -<span class="lineno" id=line32></span> <span class="big_keyword" title="Define a mutable variable">var</span> y9 = eval4 x3; <span class="comment">// ORGINAL DATA</span> |
593 |
| -<span class="lineno" id=line33></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y6; |
594 |
| -<span class="lineno" id=line34></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y7; |
595 |
| -<span class="lineno" id=line35></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y8; |
596 |
| -<span class="lineno" id=line36></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ y9; |
597 |
| -</pre></p></div></div><!--Main Content Body End--> |
| 597 | +<span class="lineno" id=line29></span> <span class="big_keyword" title="Define a mutable variable">var</span> ydd = evald xd; |
| 598 | +<span class="lineno" id=line30></span> <span class="big_keyword" title="Define a mutable variable">var</span> yda = evald xa; <span class="comment">// ORGINAL DATA</span> |
| 599 | +<span class="lineno" id=line31></span> <span class="big_keyword" title="Define a mutable variable">var</span> yds = evald xs; <span class="comment">// ORGINAL DATA</span> |
| 600 | +<span class="lineno" id=line32></span> <span class="big_keyword" title="Define a mutable variable">var</span> ydm = evald xm; <span class="comment">// ORGINAL DATA</span> |
| 601 | +<span class="lineno" id=line33></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"yd="</span>+ydd.<span class="library" title="Convert a value to a string">str</span>; |
| 602 | +<span class="lineno" id=line34></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ya="</span>+yda.<span class="library" title="Convert a value to a string">str</span>; |
| 603 | +<span class="lineno" id=line35></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ys="</span>+yds.<span class="library" title="Convert a value to a string">str</span>; |
| 604 | +<span class="lineno" id=line36></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"ym="</span>+ydm.<span class="library" title="Convert a value to a string">str</span>; |
| 605 | +</pre></p></div></div><h1 id='Open/Closed_Principle_h'><img src='/share/src/web/images/minus.gif' id='Open/Closed Principle' onclick='toggle(this,"Open/Closed_Principle_d")' alt='+'/> 2 Open/Closed Principle</h1><div id='Open/Closed_Principle_d' style='display:block'> |
| 606 | +<p>In "Object Oriented Software Construction" Bertran Meyer named a crucial |
| 607 | +system design principe the "Open/Closed Principle". It states that a system |
| 608 | +should have a unit of modularity which is simultaneously closed so it can |
| 609 | +be used and also open so it can be extended. This gave rise to the idea |
| 610 | +of classes which are closed object factories, but can be extended by |
| 611 | +inheritance. |
| 612 | +</p><p>The object oriented version of classes is a catastrophic failure bccause |
| 613 | +of severe restrictions imposed by type systems on the type of arguments of methods, |
| 614 | +which must be contravariant (or invariant), whereas usually we require covariance. |
| 615 | +</p><p>Open recursion solves this problem by providing types and function which are |
| 616 | +open to extension, and do not suffer fron the covariance problem because |
| 617 | +type variables are invariant. |
| 618 | +</p><p>The system then provides a closure operator, namely the fixpoint operator, |
| 619 | +which locks in covariant behaviour of a particular extension of the base type. |
| 620 | +The types as coproducts, which are covariant, and so base types are subtypes |
| 621 | +of extensions. This impplies the methods of an extension will continue to work |
| 622 | +with data of the base type. |
| 623 | +</p><h2 id='Issues_with_polymorphic_variants_h'><img src='/share/src/web/images/minus.gif' id='Issues with polymorphic variants' onclick='toggle(this,"Issues_with_polymorphic_variants_d")' alt='+'/> 2.1 Issues with polymorphic variants</h2><div id='Issues_with_polymorphic_variants_d' style='display:block'> |
| 624 | +<p>Polymorphic variants (as in Felix or Ocaml) are essential for open recursion |
| 625 | +to work. However as is the case with all structural types with user supplied |
| 626 | +componenmts, including records, compiler error diagnostics are very hard to |
| 627 | +understand due at least in part the fact that all the components must be listed |
| 628 | +to identify the type. By contrast, nominal types are easy to refer to, since |
| 629 | +they have a single unique and simple name. |
| 630 | +</p><p>Ocaml has made significant progress in this area by the diagnostics ability |
| 631 | +to search the symbol to table to see if a compnent set happens to have a named |
| 632 | +alias. |
| 633 | +</p></div><h2 id='Multivariant_Open_Recursion_h'><img src='/share/src/web/images/minus.gif' id='Multivariant Open Recursion' onclick='toggle(this,"Multivariant_Open_Recursion_d")' alt='+'/> 2.2 Multivariant Open Recursion</h2><div id='Multivariant_Open_Recursion_d' style='display:block'> |
| 634 | +<p>In our simple example, the open version of a type has a single type variable, |
| 635 | +and the open version of a function has a functional parameter: the type variable |
| 636 | +and the paramater are eliminated by self-reference by using the fixpoint operators. |
| 637 | +</p><p>However in complex systems such as a compiler, we usually have main types, |
| 638 | +and auxilliay types they depend on; sometimes, we have two of more major |
| 639 | +types which are convoluted and inseparable: in these cases two or more |
| 640 | +type variables and function parameters may be required |
| 641 | +</p><p>This leads to a very difficult combinatorial explosion because now we |
| 642 | +can fixate one type variable whilst leaving the other open. Multiple extensions |
| 643 | +of one type can be used with multiple extensions of another. |
| 644 | +</p><p>In Felix, the type system terms in the compiler have at least 6 auxilliary types |
| 645 | +for which multiple flat extensions cold be provided leading to an unmanagably |
| 646 | +large potential set of closed terms. of course this is <em>not</em> a problem |
| 647 | +with open recursion at all: it is a simple fact, and a blessing that open recursion |
| 648 | +provides the machine to represent these choices. The existence of fixpoint combinators |
| 649 | +are then crucial because fixation closures are anonymous and can be provided as required |
| 650 | +"on the fly". |
| 651 | +</p><p>Nevertheless, using this technology in complex applications whilst the very environment |
| 652 | +where the modularity provided is of most benefit, is also the environment where |
| 653 | +it is hardest to get right. In the Felix compiler I found it so difficult, |
| 654 | +dynamic typing was prefered; that is, handling terms that should have been |
| 655 | +erased by throwing an exception was a lot easier than constructing a type |
| 656 | +for every use case so as to obtain a compile time error. |
| 657 | +</p><p>I think it remains to develop language constructions that can leverage |
| 658 | +this technology in a more manageable way. |
| 659 | +</p></div></div><!--Main Content Body End--> |
598 | 660 |
|
599 | 661 | </div> <!-- rightpanel contents end -->
|
600 | 662 | <hr>
|
|
0 commit comments