on master help sign in
Merge pull request #378 from maxsnew/lazy
3f9170aEvan Czaplicki
libraries/Lazy.elmnew file+42
@@ -0,0 +1,42 @@
1+module Lazy ( force, lazy, map, apply, bind
2+ ) where
3+
4+{-| Library for efficient Lazy evaluation.
5+
6+# Delay
7+@docs lazy
8+
9+# Evaluate
10+@docs force
11+
12+# Transform
13+@docs map, apply, bind
14+-}
15+
16+import Basics ((<|), (.))
17+import Native.Lazy
18+
19+data Lazy a = L { force : () -> a }
20+
21+{-| Memoize a thunk so it is evaluated at most once. -}
22+lazy : (() -> a) -> Lazy a
23+lazy t = L { force = (Native.Lazy.lazy t) }
24+
25+{-| Execute a lazy value. -}
26+force : Lazy a -> a
27+force (L r) = r.force ()
28+
29+{-| Lazily apply a pure function to a lazy value. -}
30+map : (a -> b) -> Lazy a -> Lazy b
31+map f t = lazy <| \() ->
32+ f . force <| t
33+
34+{-| Lazily apply a Lazy function to a Lazy value. -}
35+apply : Lazy (a -> b) -> Lazy a -> Lazy b
36+apply f x = lazy <| \() ->
37+ (force f) (force x)
38+
39+{-| Lazily chain together Lazy computations. -}
40+bind : Lazy a -> (a -> Lazy b) -> Lazy b
41+bind x k = lazy <| \() ->
42+ force . k . force <| x
libraries/Lazy/Stream.elmnew file+121
@@ -0,0 +1,121 @@
1+module Lazy.Stream ( head, tail
2+ , cons, cons', iterate, repeat, cycle
3+ , map, apply, zip, zipWith, scanl
4+ , take, drop, splitAt
5+ , sampleOn
6+ ) where
7+
8+{-| Library for Infinite Streams
9+
10+# Create
11+@docs cons, cons', iterate, repeat, cycle
12+
13+# Observe
14+@docs head, tail, sampleOn, take, drop, splitAt
15+
16+# Transform
17+@docs map, apply, zip, zipWith, scanl
18+
19+-}
20+
21+import Basics ((.), (<|), (-), id, fst, snd)
22+import open Lazy
23+import Signal ((<~), foldp, Signal)
24+
25+data Stream a = S (Lazy (a, Stream a))
26+
27+unS : Stream a -> (a, Stream a)
28+unS (S t) = force t
29+
30+{-| Compute the first element of a Stream -}
31+head : Stream a -> a
32+head = fst . unS
33+
34+{-| Compute the next piece of a Stream -}
35+tail : Stream a -> Stream a
36+tail = snd . unS
37+
38+{-| Create a Stream -}
39+cons : a -> (() -> Stream a) -> Stream a
40+cons x txs = let mtxs = lazy txs in
41+ S . lazy <| \() ->
42+ (x, force mtxs)
43+
44+{-| Lazily create a Stream. -}
45+cons' : (() -> (a, Stream a)) -> Stream a
46+cons' = S . lazy
47+
48+{-| Create a stream of repeated applications of f to x:
49+
50+ iterate f x = S.cons x (S.cons (f x) (S.cons (f (f x)) ...))
51+-}
52+iterate : (a -> a) -> a -> Stream a
53+iterate f x = cons' <| \() ->
54+ (x, map f (iterate f x))
55+
56+{-| Create an infinite Stream of xs. -}
57+repeat : a -> Stream a
58+repeat x = iterate id x
59+
60+{-| Cycle through the elements of the nonempty list (x :: xs) -}
61+cycle : a -> [a] -> Stream a
62+cycle x xs = let cycle' ys = case ys of
63+ [] -> cons' <| \() ->
64+ (x, cycle' xs)
65+ in cycle' []
66+
67+{-| Apply a function to every element of a Stream. -}
68+map : (a -> b) -> Stream a -> Stream b
69+map f xs = cons' <| \() ->
70+ (f (head xs), map f (tail xs))
71+
72+{-| Pairwise apply a stream of functions to a stream of inputs.
73+ Together with map, generalizes zipWith to n arguments.
74+
75+ zipWith2 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
76+ zipWith2 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
77+-}
78+apply : Stream (a -> b) -> Stream a -> Stream b
79+apply fs xs = zipWith (<|) fs xs
80+
81+{-| Combine two streams, combining them into tuples pairwise. -}
82+zip : Stream a -> Stream b -> Stream (a, b)
83+zip = zipWith (\x y -> (x,y))
84+
85+{-| Combine two streams, combining them with the given function. -}
86+zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
87+zipWith f xs ys = cons' <| \() ->
88+ (f (head xs) (head ys),
89+ zipWith f (tail xs) (tail ys))
90+
91+{-| Reduce a Stream from the left, building an infinite stream of reductions. -}
92+scanl : (a -> b -> b) -> b -> Stream a -> Stream b
93+scanl f init xs = cons' <| \() ->
94+ (init,
95+ scanl f (f (head xs) init) (tail xs))
96+
97+{-| Compute the first n elements of a stream into a list. -}
98+take : Int -> Stream a -> [a]
99+take n xs = fst <| splitAt n xs
100+
101+{-| Drop n elements from the front of a stream. -}
102+drop : Int -> Stream a -> Stream a
103+drop n xs = snd <| splitAt n xs
104+
105+{-| Combination of take and drop.
106+
107+ splitAt n xs == (take n xs, drop n xs)
108+-}
109+splitAt : Int -> Stream a -> ([a], Stream a)
110+splitAt n xs = case n of
111+ 0 -> ([], xs)
112+ n -> let (heads, end) = splitAt (n - 1) (tail xs)
113+ in (head xs :: heads, end)
114+
115+{-| Turn a stream into a signal of the elements of the stream,
116+ advancing through the stream whenever an event in the given signal is
117+ fired.
118+-}
119+sampleOn : Signal b -> Stream a -> Signal a
120+sampleOn sig str = let tails = foldp (\_ -> tail) str sig in
121+ head <~ tails
libraries/Native/Lazy.jsnew file+26
@@ -0,0 +1,26 @@
1+Elm.Native.Lazy = {};
2+Elm.Native.Lazy.make = function(elm) {
3+ elm.Native = elm.Native || {};
4+ elm.Native.Lazy = elm.Native.Lazy || {};
5+
6+ if (elm.Native.Lazy.values) return elm.Native.Lazy.values;
7+
8+ var Utils = Elm.Native.Utils.make(elm);
9+
10+ function lazy(f) {
11+ var value = {};
12+ var isEvaled = false;
13+ var memoed = function(x) {
14+ if(!isEvaled) {
15+ value = f(Utils.Tuple0);
16+ isEvaled = true;
17+ }
18+ return value;
19+ }
20+ return memoed;
21+ }
22+
23+ return elm.Native.Lazy.values = {
24+ lazy : lazy
25+ };
26+};