on master help sign in
Merge pull request #456 from maxsnew/trampoline

Trampoline

commit5d5b01cb2d8cd12f46a7a74a12a57d7992e87194 authorEvan Czaplicki <info@elm-lang.org> dateFri 24 Jan 2014, 08:31 (13 years ago) parent54a2f25df135b8
2 files changed+67
libraries/Native/Trampoline.js+25 libraries/Trampoline.elm+42
libraries/Native/Trampoline.jsnew file+25
@@ -0,0 +1,25 @@
1+Elm.Native.Trampoline = {};
2+Elm.Native.Trampoline.make = function(elm) {
3+ elm.Native = elm.Native || {};
4+ elm.Native.Trampoline = elm.Native.Trampoline || {};
5+ if (elm.Native.Trampoline.values) return elm.Native.Trampoline.values;
6+
7+ var _E = Elm.Native.Error.make(elm),
8+
9+ // trampoline : Trampoline a -> a
10+ trampoline = function(t) {
11+ var tramp = t;
12+ while(true) {
13+ switch(tramp.ctor) {
14+ case "Done":
15+ return tramp._0;
16+ case "Continue":
17+ tramp = tramp._0({ctor: "_Tuple0"});
18+ continue;
19+ }
20+ _E.Case("Trampoline", "in Native.Trampoline.trampoline");
21+ }
22+ }
23+
24+ return elm.Native.Trampoline.values = { trampoline: trampoline };
25+};
libraries/Trampoline.elmnew file+42
@@ -0,0 +1,42 @@
1+module Trampoline where
2+
3+{-| Trampolining loops for unbounded recursion.
4+Since most javascript implementations lack tail-call elimination, deeply tail-recursive functions will result in a stack overflow.
5+
6+```haskell
7+fac' : Int -> Int -> Int
8+fac' n acc = if n <= 0
9+ then acc
10+ else fac' (n - 1) (n * acc)
11+
12+fac : Int -> Int
13+fac n = fac' n 1
14+
15+-- Stack overflow
16+main = asText <| fac 1000000000000
17+```
18+
19+Trampolining allows for long-running tail-recursive loops to be run without pushing calls onto the stack:
20+```haskell
21+facT : Int -> Int -> Trampoline Int
22+facT n acc = if n <= 0
23+ then Done acc
24+ else Continue <| \() -> facT (n - 1) (n * acc)
25+fac : Int -> Int
26+fac n = trampoline <| facT n 0
27+
28+-- Doesn't stack overflow
29+main = asText <| fac 1000000000000
30+```
31+# Trampoline
32+@docs Trampoline, trampoline
33+ -}
34+import Native.Trampoline
35+
36+{-| A computation that might loop. A trampoline is either the resulting value or a thunk that needs to be run more. -}
37+data Trampoline a = Done a
38+ | Continue (() -> Trampoline a)
39+
40+{-| Run a trampolining loop in constant space. -}
41+trampoline : Trampoline a -> a
42+trampoline = Native.Trampoline.trampoline