commit
5d5b01cb2d
2 changed files with 67 additions and 0 deletions
25
libraries/Native/Trampoline.js
Normal file
25
libraries/Native/Trampoline.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
Elm.Native.Trampoline = {};
|
||||
Elm.Native.Trampoline.make = function(elm) {
|
||||
elm.Native = elm.Native || {};
|
||||
elm.Native.Trampoline = elm.Native.Trampoline || {};
|
||||
if (elm.Native.Trampoline.values) return elm.Native.Trampoline.values;
|
||||
|
||||
var _E = Elm.Native.Error.make(elm),
|
||||
|
||||
// trampoline : Trampoline a -> a
|
||||
trampoline = function(t) {
|
||||
var tramp = t;
|
||||
while(true) {
|
||||
switch(tramp.ctor) {
|
||||
case "Done":
|
||||
return tramp._0;
|
||||
case "Continue":
|
||||
tramp = tramp._0({ctor: "_Tuple0"});
|
||||
continue;
|
||||
}
|
||||
_E.Case("Trampoline", "in Native.Trampoline.trampoline");
|
||||
}
|
||||
}
|
||||
|
||||
return elm.Native.Trampoline.values = { trampoline: trampoline };
|
||||
};
|
42
libraries/Trampoline.elm
Normal file
42
libraries/Trampoline.elm
Normal file
|
@ -0,0 +1,42 @@
|
|||
module Trampoline where
|
||||
|
||||
{-| Trampolining loops for unbounded recursion.
|
||||
Since most javascript implementations lack tail-call elimination, deeply tail-recursive functions will result in a stack overflow.
|
||||
|
||||
```haskell
|
||||
fac' : Int -> Int -> Int
|
||||
fac' n acc = if n <= 0
|
||||
then acc
|
||||
else fac' (n - 1) (n * acc)
|
||||
|
||||
fac : Int -> Int
|
||||
fac n = fac' n 1
|
||||
|
||||
-- Stack overflow
|
||||
main = asText <| fac 1000000000000
|
||||
```
|
||||
|
||||
Trampolining allows for long-running tail-recursive loops to be run without pushing calls onto the stack:
|
||||
```haskell
|
||||
facT : Int -> Int -> Trampoline Int
|
||||
facT n acc = if n <= 0
|
||||
then Done acc
|
||||
else Continue <| \() -> facT (n - 1) (n * acc)
|
||||
fac : Int -> Int
|
||||
fac n = trampoline <| facT n 0
|
||||
|
||||
-- Doesn't stack overflow
|
||||
main = asText <| fac 1000000000000
|
||||
```
|
||||
# Trampoline
|
||||
@docs Trampoline, trampoline
|
||||
-}
|
||||
import Native.Trampoline
|
||||
|
||||
{-| A computation that might loop. A trampoline is either the resulting value or a thunk that needs to be run more. -}
|
||||
data Trampoline a = Done a
|
||||
| Continue (() -> Trampoline a)
|
||||
|
||||
{-| Run a trampolining loop in constant space. -}
|
||||
trampoline : Trampoline a -> a
|
||||
trampoline = Native.Trampoline.trampoline
|
Loading…
Reference in a new issue