You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+54Lines changed: 54 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -475,6 +475,60 @@ def pure sin(x: Int) -> Int := [
475
475
]
476
476
```
477
477
478
+
### 🤚 Total functions (🇻 0.5+)
479
+
480
+
A function may also be total, which means:
481
+
482
+
1. It is defined for possible values of its domain
483
+
2. It will halt on all such inputs
484
+
485
+
The second property is interesting, because that would imply that the compiler can prove that an arbitrary function can halt.
486
+
To build such a compiler, we would need to solve the halting problem (which is impossible).
487
+
Instead, we place heavy restrictions on total functions, enforcing that they are weakly normalizing:
488
+
489
+
1. We may only call total functions
490
+
2. Within the _call tree_ of a function, all arguments to nodes in the tree must be _strictly decreasing_ compared to the first parent of a node which is equal to said node.
491
+
3. Potentially non-terminating `while` loops are not allowed
492
+
4. For may only be called over collections which implement `SizedIterator`, which is also implemented by the built-in:
493
+
-`RangeToInclusive` : `..=b`
494
+
-`RangeTo` : `..b`
495
+
-`Range` : `a..b`
496
+
-`RangeInclusive` : `a..=b`
497
+
498
+
Take for instance this naive implementation of the Fibbonaci sequence:
499
+
500
+
```mamba
501
+
## fibbonaci, implemented using recursion and not dynamic programming
502
+
def total pure fibbonaci(x: PosInt) -> Int := match x {
503
+
0 => 0
504
+
1 => 1
505
+
n => fibbonaci(n - 1) + fibbonaci(n - 2)
506
+
}
507
+
```
508
+
509
+
This would, with some subsitution magic, give the following _call tree_:
510
+
511
+
```
512
+
fibbonaci(x)
513
+
/ \
514
+
fibbonaci(x - 1) fibbonaci(x - 2)
515
+
```
516
+
517
+
Thus, this function has the property of a final function, and we may thus mark it as `total` if we so choose.
518
+
The reason why we above state "compared to the first parent of a node which is equal to said node." is that we can have situations where we call other total functions which have recursive calls to self.
519
+
This allows us to call other recursive functions without having to strictly decrease the value of the input, but still enfroce that calls to self (and more generally recursive calls to the same function) again are strictly decreasing.
520
+
This strictly decreasing property is likely difficult to prove, so we will limit this to a set of primtives at first.
521
+
522
+
In general:
523
+
524
+
- If a function is `pure`, it has no side effects.
525
+
- If a function is `total`, it will terminate for all possible inputs.
526
+
527
+
One does not imply the other, so you need both keywords if you want to say a function is total and pure.
528
+
529
+
The intended use-case is a bit more niche, likely mostly functions in the standard library, to show that they halt on all possible inputs.
530
+
But we can imagine that library writers might find these useful if they wish to be more thorough.
531
+
478
532
### ⚠ Error handling
479
533
480
534
Unlike Python, Mamba does not have `try``except` and `finally` (or `try``catch` as it is sometimes known).
0 commit comments