on master help sign in
Merge remote-tracking branch 'evan/dev' into topic/webgl
commitb9e10b4bef7b26b216749de374aa7cecbd800c3e authorJohn P Mayer Jr <john.p.mayer.jr@gmail.com> dateWed 11 Dec 2013, 00:21 (13 years ago) parentf349ea832d1627
7 files changed+271−12
changelog.txt+2 compiler/Transform/Check.hs+18−7 libraries/Lazy.elm+42 libraries/Lazy/Stream.elm+125 libraries/List.elm+42 libraries/Native/Lazy.js+26 libraries/Native/List.js+16−5
changelog.txt+2
@@ -1,6 +1,8 @@
11
22## 0.11
33
4+ * Lazy and Lazy.Stream (thanks to Max New)
5+ * sortBy, sortWith (thanks to Max Goldstein)
46 * elm-repl
57 * Markdown interpolation
68 * Bitwise library
compiler/Transform/Check.hs+18−7
@@ -17,11 +17,11 @@ mistakes :: (Data t, Data v) => [Declaration t v] -> [Doc]
1717mistakes decls =
1818 concat [ infiniteTypeAliases decls
1919 , illFormedTypes decls
20+ , map P.text (duplicateConstructors decls)
2021 , map P.text (concatMap findErrors (getLets decls)) ]
2122 where
2223 findErrors defs = duplicates defs ++ badOrder defs
2324
24−
2525getLets :: (Data t, Data v) => [Declaration t v] -> [[Def t v]]
2626getLets decls = defs : concatMap getSubLets defs
2727 where
@@ -32,6 +32,12 @@ getLets decls = defs : concatMap getSubLets defs
3232 Def pattern expr -> [ defs | Let defs _ <- universeBi expr ]
3333 TypeAnnotation _ _ -> []
3434
35+dups :: Eq a => [a] -> [a]
36+dups = map head . filter ((>1) . length) . List.group
37+
38+dupErr :: String -> String -> String
39+dupErr err x =
40+ "Syntax Error: There can only be one " ++ err ++ " '" ++ x ++ "'."
3541
3642duplicates :: [Def t v] -> [String]
3743duplicates defs =
@@ -39,13 +45,18 @@ duplicates defs =
3945 where
4046 annotations = List.sort [ name | TypeAnnotation name _ <- defs ]
4147 definitions = List.sort $ concatMap Set.toList [ boundVars pattern | Def pattern _ <- defs ]
48+ defMsg = dupErr "definition of"
49+ annMsg = dupErr "type annotation for"
4250
43− dups = map head . filter ((>1) . length) . List.group
44−
45− msg = "Syntax Error: There can only be one "
46− defMsg x = msg ++ "definition of '" ++ x ++ "'."
47− annMsg x = msg ++ "type annotation for '" ++ x ++ "'."
48−
51+duplicateConstructors :: [Declaration t v] -> [String]
52+duplicateConstructors decls =
53+ map typeMsg (dups typeCtors) ++ map dataMsg (dups dataCtors)
54+ where
55+ typeCtors = List.sort [ name | Datatype name _ _ <- decls ]
56+ dataCtors = List.sort . concat $
57+ [ map fst patterns | Datatype _ _ patterns <- decls ]
58+ dataMsg = dupErr "definition of data constructor"
59+ typeMsg = dupErr "definition of type constructor"
4960
5061badOrder :: [Def t v] -> [String]
5162badOrder defs = go defs
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+125
@@ -0,0 +1,125 @@
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, iterate f (f x))
55+
56+{-| Create an infinite Stream of xs. -}
57+repeat : a -> Stream a
58+repeat x = let go = cons x <| \() -> go
59+ in go
60+
61+{-| Cycle through the elements of the nonempty list (x :: xs) -}
62+cycle : a -> [a] -> Stream a
63+cycle x xs = let cycle' ys = case ys of
64+ [] -> go
65+ (y :: ys) -> cons y <| \() ->
66+ cycle' ys
67+ go = cons' <| \() ->
68+ (x, cycle' xs)
69+ in go
70+
71+{-| Apply a function to every element of a Stream. -}
72+map : (a -> b) -> Stream a -> Stream b
73+map f xs = cons' <| \() ->
74+ (f (head xs), map f (tail xs))
75+
76+{-| Pairwise apply a stream of functions to a stream of inputs.
77+ Together with map, generalizes zipWith to n arguments.
78+
79+ zipWith2 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
80+ zipWith2 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
81+-}
82+apply : Stream (a -> b) -> Stream a -> Stream b
83+apply fs xs = zipWith (<|) fs xs
84+
85+{-| Combine two streams, combining them into tuples pairwise. -}
86+zip : Stream a -> Stream b -> Stream (a, b)
87+zip = zipWith (\x y -> (x,y))
88+
89+{-| Combine two streams, combining them with the given function. -}
90+zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
91+zipWith f xs ys = cons' <| \() ->
92+ (f (head xs) (head ys),
93+ zipWith f (tail xs) (tail ys))
94+
95+{-| Reduce a Stream from the left, building an infinite stream of reductions. -}
96+scanl : (a -> b -> b) -> b -> Stream a -> Stream b
97+scanl f init xs = cons' <| \() ->
98+ (init,
99+ scanl f (f (head xs) init) (tail xs))
100+
101+{-| Compute the first n elements of a stream into a list. -}
102+take : Int -> Stream a -> [a]
103+take n xs = fst <| splitAt n xs
104+
105+{-| Drop n elements from the front of a stream. -}
106+drop : Int -> Stream a -> Stream a
107+drop n xs = snd <| splitAt n xs
108+
109+{-| Combination of take and drop.
110+
111+ splitAt n xs == (take n xs, drop n xs)
112+-}
113+splitAt : Int -> Stream a -> ([a], Stream a)
114+splitAt n xs = case n of
115+ 0 -> ([], xs)
116+ n -> let (heads, end) = splitAt (n - 1) (tail xs)
117+ in (head xs :: heads, end)
118+
119+{-| Turn a stream into a signal of the elements of the stream,
120+ advancing through the stream whenever an event in the given signal is
121+ fired.
122+-}
123+sampleOn : Signal b -> Stream a -> Signal a
124+sampleOn sig str = let tails = foldp (\_ -> tail) str sig in
125+ head <~ tails
libraries/List.elm+42
@@ -20,6 +20,9 @@ list must have the same type.
2020
2121# Special Folds
2222@docs sum, product, maximum, minimum, all, any, and, or
23+
24+# Sorting
25+@docs sort, sortBy, sortWith
2326-}
2427
2528import open Basics
@@ -224,3 +227,42 @@ drop = Native.List.drop
224227-}
225228repeat : Int -> a -> [a]
226229repeat = Native.List.repeat
230+
231+{-| Sort values from lowest to highest: `sort [3,1,5] == [1,3,5]`
232+-}
233+sort : [comparable] -> [comparable]
234+sort = Native.List.sort
235+
236+{-| Sort values by a derived property.
237+
238+```haskell
239+alice = { name="Alice", height=1.62 }
240+bob = { name="Bob" , height=1.85 }
241+chuck = { name="Chuck", height=1.76 }
242+
243+sortBy .name [chuck,alice,bob] == [alice,bob,chuck]
244+sortBy .height [chuck,alice,bob] == [alice,chuck,bob]
245+
246+sortBy String.length ["five","hi"] == ["hi","five"]
247+```
248+-}
249+sortBy : (a -> comparable) -> [a] -> [a]
250+sortBy = Native.List.sortBy
251+
252+{-| Sort values with a custom comparison function.
253+
254+```haskell
255+sortWith flippedComparison [1..5] == [5,4,3,2,1]
256+
257+flippedComparison a b =
258+ case compare a b of
259+ LT -> GT
260+ EQ -> EQ
261+ GT -> LT
262+```
263+
264+This is also the most general sort function, allowing you
265+to define any other: `sort == sortWith compare`
266+-}
267+sortWith : (a -> a -> Order) -> [a] -> [a]
268+sortWith = Native.List.sortWith
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+};
libraries/Native/List.js+16−5
@@ -220,11 +220,20 @@ Elm.Native.List.make = function(elm) {
220220 }
221221
222222 function sort(xs) {
223− function cmp(a,b) {
224− var ord = Utils.compare(a,b).ctor;
225− return ord=== 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
226− }
227− return fromArray(toArray(xs).sort(cmp));
223+ return fromArray(toArray(xs).sort(Utils.cmp));
224+ }
225+
226+ function sortBy(f, xs) {
227+ return fromArray(toArray(xs).sort(function(a,b){
228+ return Utils.cmp(f(a), f(b));
229+ }));
230+ }
231+
232+ function sortWith(f, xs) {
233+ return fromArray(toArray(xs).sort(function(a,b){
234+ var ord = f(a)(b).ctor;
235+ return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
236+ }));
228237 }
229238
230239 function nth(xs, n) {
@@ -322,6 +331,8 @@ Elm.Native.List.make = function(elm) {
322331 zipWith:F3(zipWith),
323332 zip:F2(zip),
324333 sort:sort,
334+ sortBy:F2(sortBy),
335+ sortWith:F2(sortWith),
325336 nth:F2(nth),
326337 take:F2(take),
327338 drop:F2(drop),