on master help sign in
Merge branch 'master' into dev
commitd8ced9ee74c8894f717fcac795ce8bbdedff4165 authorEvan Czaplicki <info@elm-lang.org> dateMon 28 Oct 2013, 11:27 (13 years ago) parent464c4e85f82630
22 files changed+212−100
Elm.cabal+3−3 README.md+4−5 compiler/Generate/JavaScript.hs+15−9 compiler/Parse/Type.hs+13−10 compiler/SourceSyntax/Declaration.hs+24−1 compiler/Transform/Check.hs+46−2 libraries/AutomatonV2.elm → libraries/AutomatonV2.elm.hidden libraries/Color.elm+1−1 libraries/Either.elm−12 libraries/Graphics/Collage.elm+11−11 libraries/Graphics/Element.elm+7−8 libraries/JavaScript.elm+1−1 libraries/Maybe.elm−5 libraries/Native/Basics.js+1−1 libraries/Native/Show.js+1−1 libraries/Native/Signal/Http.js+3−4 libraries/Native/String.js+29−10 libraries/Random.elm+1−1 libraries/Signal.elm+3−3 libraries/String.elm+45−8 runtime/Render/Utils.js+2−2 server/elm-server.cabal+2−2
Elm.cabal+3−3
@@ -1,5 +1,5 @@
11Name: Elm
2−Version: 0.9.0.2
2+Version: 0.10.0.2
33Synopsis: The Elm language module.
44Description: Elm aims to make client-side web-development more pleasant.
55 It is a statically/strongly typed, functional reactive
@@ -88,7 +88,7 @@ Library
8888 directory,
8989 filepath,
9090 indents,
91− language-ecmascript,
91+ language-ecmascript < 1,
9292 mtl >= 2,
9393 pandoc >= 1.10,
9494 parsec >= 3.1.1,
@@ -157,7 +157,7 @@ Executable elm
157157 directory,
158158 filepath,
159159 indents,
160− language-ecmascript,
160+ language-ecmascript < 1,
161161 mtl >= 2,
162162 pandoc >= 1.10,
163163 parsec >= 3.1.1,
README.md+4−5
@@ -3,8 +3,7 @@ Learn about the Elm programming language at [elm-lang.org](http://elm-lang.org/)
33
44## Install
55
6−Download the [Haskell Platform 2012.2.0.0](http://hackage.haskell.org/platform/).
7−Elm definitely works with GHC 7.4, so newer versions of the Haskell Platform may work too.
6+Download the [Haskell Platform 2012.2.0.0 or later](http://hackage.haskell.org/platform/).
87Once the Haskell Platform is installed:
98
109 cabal update
@@ -39,10 +38,10 @@ commands place a simple program into `Main.elm`. Do this manually if you do not
3938have `printf`. The final command starts the Elm server at [localhost:8000](http://localhost:8000/),
4039allowing you to navigate to `Main.elm` and see your first program in action.
4140
42−#### Wrap up
41+#### Final Notes
4342
44−The `elm` package provides support for compilation of Elm code directly in Haskell and QuasiQuoting.
45−Check it out on Hackage if you are interested.
43+The `elm` package provides support for compilation of Elm code directly in Haskell.
44+Check it out [on Hackage](http://hackage.haskell.org/package/Elm) if you are interested.
4645
4746If you are stuck, email [the list](https://groups.google.com/forum/?fromgroups#!forum/elm-discuss)
4847or ask a question in the [#Elm IRC channel](http://webchat.freenode.net/?channels=elm).
compiler/Generate/JavaScript.hs+15−9
@@ -243,14 +243,17 @@ match :: (Show a) => a -> Case.Match () () -> State Int [Statement ()]
243243match span mtch =
244244 case mtch of
245245 Case.Match name clauses mtch' ->
246− do clauses' <- mapM (clause span name) clauses
246+ do (isChars, clauses') <- unzip <$> mapM (clause span name) clauses
247247 mtch'' <- match span mtch'
248− return (SwitchStmt () (access name) clauses' : mtch'')
248+ return (SwitchStmt () (format isChars (access name)) clauses' : mtch'')
249249 where
250250 isLiteral p = case p of
251251 Case.Clause (Right _) _ _ -> True
252252 _ -> False
253253 access name = if any isLiteral clauses then ref name else dotSep [name,"ctor"]
254+ format isChars e
255+ | or isChars = InfixExpr () OpAdd e (string "")
256+ | otherwise = e
254257
255258 Case.Fail ->
256259 return [ ExprStmt () (obj "_E.Case" `call` [ref "$moduleName", string (show span)]) ]
@@ -268,15 +271,18 @@ match span mtch =
268271 _ -> dropEnd (acc ++ [m]) ms
269272
270273clause span variable (Case.Clause value vars mtch) =
271− CaseClause () pattern <$> match span (Case.matchSubst (zip vars vars') mtch)
274+ (,) isChar . CaseClause () pattern <$> match span (Case.matchSubst (zip vars vars') mtch)
272275 where
273276 vars' = map (\n -> variable ++ "._" ++ show n) [0..]
274− pattern = case value of
275− Right (Boolean b) -> BoolLit () b
276− Right lit -> literal lit
277− Left name -> string $ case List.elemIndices '.' name of
278− [] -> name
279− is -> drop (last is + 1) name
277+ (isChar, pattern) =
278+ case value of
279+ Right (Chr c) -> (True, string [c])
280+ _ -> (,) False $ case value of
281+ Right (Boolean b) -> BoolLit () b
282+ Right lit -> literal lit
283+ Left name -> string $ case List.elemIndices '.' name of
284+ [] -> name
285+ is -> drop (last is + 1) name
280286
281287
282288jsModule :: MetadataModule () () -> String
compiler/Parse/Type.hs+13−10
@@ -25,19 +25,22 @@ tuple = do ts <- parens (commaSep expr)
2525record :: IParser T.Type
2626record =
2727 do char '{' ; whitespace
28− ext <- extend
29− fs <- fields
28+ (ext,fs) <- extended <|> normal
3029 dumbWhitespace ; char '}'
3130 return (T.Record fs ext)
3231 where
33− extend = option T.EmptyRecord . try $ do
34− t <- tvar
35− whitespace >> string "|" >> whitespace
36− return t
37− fields = commaSep1 $ do
38− lbl <- rLabel
39− whitespace >> hasType >> whitespace
40− (,) lbl <$> expr
32+ normal = (,) T.EmptyRecord <$> commaSep fields
33+
34+ -- extended record types require at least one field
35+ extended = do
36+ ext <- try (const <$> tvar <*> (whitespace >> string "|"))
37+ whitespace
38+ (,) ext <$> commaSep1 fields
39+
40+ fields = do
41+ lbl <- rLabel
42+ whitespace >> hasType >> whitespace
43+ (,) lbl <$> expr
4144
4245capTypeVar = intercalate "." <$> dotSep1 capVar
4346
compiler/SourceSyntax/Declaration.hs+24−1
@@ -4,6 +4,8 @@ module SourceSyntax.Declaration where
44import Data.Data
55import qualified SourceSyntax.Expression as Expr
66import SourceSyntax.Type
7+import SourceSyntax.PrettyPrint
8+import Text.PrettyPrint as P
79
810data Declaration tipe var
911 = Definition (Expr.Def tipe var)
@@ -22,4 +24,25 @@ instance Show Assoc where
2224 case assoc of
2325 L -> "left"
2426 N -> "non"
25− R -> "right"
27+ R -> "right"
28+
29+instance Pretty (Declaration t v) where
30+ pretty decl =
31+ case decl of
32+ Definition def -> pretty def
33+
34+ Datatype tipe tvars ctors ->
35+ P.hang (P.text "data" <+> P.text tipe <+> P.hsep (map P.text tvars)) 4
36+ (P.sep $ zipWith join ("=" : repeat "|") ctors)
37+ where
38+ join c ctor = P.text c <+> prettyCtor ctor
39+ prettyCtor (name, tipes) =
40+ P.hang (P.text name) 2 (P.sep (map prettyParens tipes))
41+
42+ TypeAlias name tvars tipe ->
43+ let alias = P.text name <+> P.hsep (map P.text tvars) in
44+ P.hang (P.text "type" <+> alias <+> P.equals) 4 (pretty tipe)
45+
46+ -- TODO: actually write out the other cases. They are currently unused, but
47+ -- this is probably going to be a bug someday.
48+ _ -> P.text (show decl)
compiler/Transform/Check.hs+46−2
@@ -2,9 +2,11 @@ module Transform.Check (mistakes) where
22
33import Transform.SortDefinitions (boundVars)
44import SourceSyntax.Everything
5+import SourceSyntax.PrettyPrint
56import qualified SourceSyntax.Type as T
67import Data.List as List
78import qualified Data.Map as Map
9+import qualified Data.Maybe as Maybe
810import qualified Data.Set as Set
911import Data.Data
1012import Data.Generics.Uniplate.Data
@@ -13,7 +15,7 @@ import Text.PrettyPrint as P
1315
1416mistakes :: (Data t, Data v) => [Declaration t v] -> [Doc]
1517mistakes decls =
16− map P.text $ concatMap findErrors (getLets decls)
18+ illFormedTypes decls ++ map P.text (concatMap findErrors (getLets decls))
1719 where
1820 findErrors defs = duplicates defs ++ badOrder defs
1921
@@ -60,4 +62,46 @@ badOrder defs = go defs
6062
6163 _ -> []
6264
63−
65+illFormedTypes :: [Declaration t v] -> [Doc]
66+illFormedTypes decls = map report (Maybe.mapMaybe isIllFormed (aliases ++ adts))
67+ where
68+ aliases = [ (decl, tvars, [tipe]) | decl@(TypeAlias _ tvars tipe) <- decls ]
69+ adts = [ (decl, tvars, concatMap snd ctors) | decl@(Datatype _ tvars ctors) <- decls ]
70+
71+ freeVars tipe =
72+ case tipe of
73+ T.Lambda t1 t2 -> Set.union (freeVars t1) (freeVars t2)
74+ T.Var x -> Set.singleton x
75+ T.Data _ ts -> Set.unions (map freeVars ts)
76+ T.EmptyRecord -> Set.empty
77+ T.Record fields ext -> Set.unions (freeVars ext : map (freeVars . snd) fields)
78+
79+ undeclared tvars tipes = Set.difference used declared
80+ where
81+ used = Set.unions (map freeVars tipes)
82+ declared = Set.fromList tvars
83+
84+ isIllFormed (decl, tvars, tipes) =
85+ let unbound = undeclared tvars tipes in
86+ if Set.null unbound then Nothing
87+ else Just (decl, Set.toList unbound)
88+
89+ report (decl, tvars) =
90+ P.vcat [ P.text $ "Error: type variable" ++ listing ++ " unbound in:"
91+ , P.text "\n"
92+ , nest 4 (pretty decl) ]
93+ where
94+ listing =
95+ case tvars of
96+ [tvar] -> " " ++ quote tvar ++ " is"
97+ _ -> "s" ++ addCommas (map ((++) " ") (addAnd (map quote tvars))) ++ " are"
98+
99+ addCommas xs
100+ | length xs < 3 = concat xs
101+ | otherwise = intercalate "," xs
102+
103+ addAnd xs
104+ | length xs < 2 = xs
105+ | otherwise = zipWith (++) (replicate (length xs - 1) "" ++ ["and "]) xs
106+
107+ quote tvar = "'" ++ tvar ++ "'"
libraries/AutomatonV2.elm → libraries/AutomatonV2.elm.hiddenrenamed

The content is the same.

libraries/Color.elm+1−1
@@ -6,7 +6,7 @@ module Color where
66built-in names.
77
88# Creation
9−@docs rgb, rgba, hsv, hsva, grayscale, greyscale
9+@docs rgb, rgba, hsv, hsva, greyscale, grayscale
1010
1111# From Other Colors
1212@docs complement
libraries/Either.elm−12
@@ -52,28 +52,16 @@ have the equivalence: `(partition es == (lefts es, rights es))`
5252partition : [Either a b] -> ([a],[b])
5353partition es = List.foldr consEither ([],[]) es
5454
55−{-| If `Left`, add the value to the front of the list.
56−If `Right`, return the list unchanged
57−-}
58−consLeft : Either a b -> [a] -> [a]
5955consLeft e vs =
6056 case e of
6157 Left v -> v::vs
6258 Right _ -> vs
6359
64−{-| If `Right`, add the value to the front of the list.
65−If `Left`, return the list unchanged.
66−-}
67−consRight : Either a b -> [b] -> [b]
6860consRight e vs =
6961 case e of
7062 Left _ -> vs
7163 Right v -> v::vs
7264
73−{-| If `Left`, add the value to the left list.
74−If `Right`, add the value to the right list.
75−-}
76−consEither : Either a b -> ([a], [b]) -> ([a], [b])
7765consEither e (ls,rs) =
7866 case e of
7967 Left l -> (l::ls,rs)
libraries/Graphics/Collage.elm+11−11
@@ -125,7 +125,7 @@ tiled to fill the entire shape.
125125textured : String -> Shape -> Form
126126textured src shape = fill (Texture src) shape
127127
128−{-| Fill a shape with a [gradient](/docs/Color.elm#linear). -}
128+{-| Fill a shape with a [gradient](/library/Color.elm#linear). -}
129129gradient : Gradient -> Shape -> Form
130130gradient grad shape = fill (Grad grad) shape
131131
@@ -204,37 +204,37 @@ collage : Int -> Int -> [Form] -> Element
204204collage = Native.Graphics.Collage.collage
205205
206206
207−type Path = [(number,number)]
207+type Path = [(Float,Float)]
208208
209209{-| Create a path that follows a sequence of points. -}
210−path : [(number,number)] -> Path
210+path : [(Float,Float)] -> Path
211211path ps = ps
212212
213213{-| Create a path along a given line segment. -}
214−segment : (number,number) -> (number,number) -> Path
214+segment : (Float,Float) -> (Float,Float) -> Path
215215segment p1 p2 = [p1,p2]
216216
217−type Shape = [(number,number)]
217+type Shape = [(Float,Float)]
218218
219219{-| Create an arbitrary polygon by specifying its corners in order.
220220`polygon` will automatically close all shapes, so the given list
221221of points does not need to start and end with the same position.
222222-}
223−polygon : [(number,number)] -> Shape
223+polygon : [(Float,Float)] -> Shape
224224polygon points = points
225225
226226{-| A rectangle with a given width and height. -}
227−rect : number -> number -> Shape
227+rect : Float -> Float -> Shape
228228rect w h = let hw = w/2
229229 hh = h/2
230230 in [ (0-hw,0-hh), (0-hw,hh), (hw,hh), (hw,0-hh) ]
231231
232232{-| A square with a given edge length. -}
233−square : number -> Shape
233+square : Float -> Shape
234234square n = rect n n
235235
236236{-| An oval with a given width and height. -}
237−oval : number -> number -> Shape
237+oval : Float -> Float -> Shape
238238oval w h =
239239 let n = 50
240240 t = 2 * pi / n
@@ -244,7 +244,7 @@ oval w h =
244244 in List.map f [0..n-1]
245245
246246{-| A circle with a given radius. -}
247−circle : number -> Shape
247+circle : Float -> Shape
248248circle r = oval (2*r) (2*r)
249249
250250{-| A regular polygon with N sides. The first argument specifies the number
@@ -253,7 +253,7 @@ of sides and the second is the radius. So to create a pentagon with radius
253253
254254 ngon 5 30
255255-}
256−ngon : Int -> number -> Shape
256+ngon : Int -> Float -> Shape
257257ngon n r =
258258 let m = toFloat n
259259 t = 2 * pi / m
libraries/Graphics/Element.elm+7−8
@@ -204,9 +204,8 @@ flow dir es =
204204 DIn -> newFlow (List.maximum ws) (List.maximum hs)
205205 DOut -> newFlow (List.maximum ws) (List.maximum hs)
206206
207−{-| Stack elements vertically. To put `a` above `b` you would say:
208−
209− a `above` b
207+{-| Stack elements vertically.
208+To put `a` above `b` you would say: ``a `above` b``
210209-}
211210above : Element -> Element -> Element
212211above hi lo =
@@ -214,9 +213,8 @@ above hi lo =
214213 (heightOf hi + heightOf lo)
215214 (Flow DDown [hi,lo])
216215
217−{-| Stack elements vertically. To put `a` below `b` you would say:
218−
219− a `below` b
216+{-| Stack elements vertically.
217+To put `a` below `b` you would say: ``a `below` b``
220218-}
221219below : Element -> Element -> Element
222220below lo hi =
@@ -225,6 +223,7 @@ below lo hi =
225223 (Flow DDown [hi,lo])
226224
227225{-| Put elements beside each other horizontally.
226+To put `a` beside `b` you would say: ``a `beside` b``
228227-}
229228beside : Element -> Element -> Element
230229beside lft rht =
@@ -232,8 +231,8 @@ beside lft rht =
232231 (max (heightOf lft) (heightOf rht))
233232 (Flow right [lft,rht])
234233
235−{-| Layer elements on top of each other, starting from the bottom.
236−`(layers == flow outward)`
234+{-| Layer elements on top of each other, starting from the bottom:
235+`layers == flow outward`
237236-}
238237layers : [Element] -> Element
239238layers es =
libraries/JavaScript.elm+1−1
@@ -9,7 +9,7 @@ integration.
99@docs toString, toInt, toFloat, toBool, toList
1010
1111# JavaScript from Elm
12−@docs fromString, fromInt, fromFloat, fromBool fromList
12+@docs fromString, fromInt, fromFloat, fromBool, fromList
1313-}
1414{-
1515# DOM Nodes and Elements
libraries/Maybe.elm−5
@@ -39,11 +39,6 @@ isJust = maybe False (\_ -> True)
3939isNothing : Maybe a -> Bool
4040isNothing = not . isJust
4141
42−
43−{-| If `Just`, adds the value to the front of the list.
44−If `Nothing`, list is unchanged.
45−-}
46−cons : Maybe a -> [a] -> [a]
4742cons mx xs = maybe xs (\x -> x :: xs) mx
4843
4944{-| Filters out Nothings and extracts the remaining values.
libraries/Native/Basics.js+1−1
@@ -33,7 +33,7 @@ Elm.Native.Basics.make = function(elm) {
3333 mod:mod,
3434
3535 pi:Math.PI,
36− e:Math.e,
36+ e:Math.E,
3737 cos:Math.cos,
3838 sin:Math.sin,
3939 tan:Math.tan,
libraries/Native/Show.js+1−1
@@ -21,7 +21,7 @@ Elm.Native.Show.make = function(elm) {
2121 return v ? "True" : "False";
2222 } else if (type === "number") {
2323 return v+"";
24− } else if (v.isChar && v instanceof String) {
24+ } else if ((v instanceof String) && v.isChar) {
2525 return "'" + addSlashes(v) + "'";
2626 } else if (type === "string") {
2727 return '"' + addSlashes(v) + '"';
libraries/Native/Signal/Http.js+3−4
@@ -26,10 +26,6 @@ Elm.Native.Http.make = function(elm) {
2626 }
2727 }
2828
29− function setHeader(pair) {
30− request.setRequestHeader( JS.fromString(pair._0), JS.fromString(pair._1) );
31− }
32−
3329 function sendReq(queue,responses,req) {
3430 var response = { value: { ctor:'Waiting' } };
3531 queue.push(response);
@@ -46,6 +42,9 @@ Elm.Native.Http.make = function(elm) {
4642 }
4743 };
4844 request.open(JS.fromString(req.verb), JS.fromString(req.url), true);
45+ function setHeader(pair) {
46+ request.setRequestHeader( JS.fromString(pair._0), JS.fromString(pair._1) );
47+ }
4948 List.map(setHeader)(req.headers);
5049 request.send(JS.fromString(req.body));
5150 }
libraries/Native/String.js+29−10
@@ -22,14 +22,24 @@ Elm.Native.String.make = function(elm) {
2222 return (hd = str[0]) ? Maybe.Just(Utils.Tuple2(Utils.chr(hd), str.slice(1)))
2323 : Maybe.Nothing;
2424 }
25+ function append(a,b) {
26+ return a + b;
27+ }
28+ function concat(strs) {
29+ return JS.fromList(strs).join('');
30+ }
2531 function length(str) {
2632 return str.length;
2733 }
2834 function map(f,str) {
29− return str.split('').map(f).join('');
35+ var out = str.split('');
36+ for (var i = out.length; i--; ) {
37+ out[i] = f(Utils.chr(out[i]));
38+ }
39+ return out.join('');
3040 }
3141 function filter(pred,str) {
32− return str.split('').filter(pred).join('');
42+ return str.split('').map(Utils.chr).filter(pred).join('');
3343 }
3444 function reverse(str) {
3545 return str.split('').reverse().join('');
@@ -37,13 +47,13 @@ Elm.Native.String.make = function(elm) {
3747 function foldl(f,b,str) {
3848 var len = str.length;
3949 for (var i = 0; i < len; ++i) {
40− b = A2(f, str[i], b);
50+ b = A2(f, Utils.chr(str[i]), b);
4151 }
4252 return b;
4353 }
4454 function foldr(f,b,str) {
4555 for (var i = str.length; i--; ) {
46− b = A2(f, str[i], b);
56+ b = A2(f, Utils.chr(str[i]), b);
4757 }
4858 return b;
4959 }
@@ -116,13 +126,13 @@ Elm.Native.String.make = function(elm) {
116126
117127 function any(pred, str) {
118128 for (var i = str.length; i--; ) {
119− if (pred(str[i])) return true;
129+ if (pred(Utils.chr(str[i]))) return true;
120130 }
121131 return false;
122132 }
123133 function all(pred, str) {
124134 for (var i = str.length; i--; ) {
125− if (!pred(str[i])) return false;
135+ if (!pred(Utils.chr(str[i]))) return false;
126136 }
127137 return true;
128138 }
@@ -147,8 +157,7 @@ Elm.Native.String.make = function(elm) {
147157 return JS.toList(is);
148158 }
149159
150− function toInt(str) {
151− var s = JS.fromString(str);
160+ function toInt(s) {
152161 var len = s.length;
153162 if (len === 0) { return Maybe.Nothing; }
154163 var start = 0;
@@ -162,8 +171,7 @@ Elm.Native.String.make = function(elm) {
162171 return Maybe.Just(parseInt(s, 10));
163172 }
164173
165− function toFloat(str) {
166− var s = JS.fromString(str);
174+ function toFloat(s) {
167175 var len = s.length;
168176 if (len === 0) { return Maybe.Nothing; }
169177 var start = 0;
@@ -183,10 +191,19 @@ Elm.Native.String.make = function(elm) {
183191 return Maybe.Just(parseFloat(s));
184192 }
185193
194+ function toList(str) {
195+ return JS.toList(str.split('').map(Utils.chr));
196+ }
197+ function fromList(chars) {
198+ return JS.fromList(chars).join('');
199+ }
200+
186201 return Elm.Native.String.values = {
187202 isEmpty: isEmpty,
188203 cons: F2(cons),
189204 uncons: uncons,
205+ append: F2(append),
206+ concat: concat,
190207 length: length,
191208 map: F2(map),
192209 filter: F2(filter),
@@ -228,5 +245,7 @@ Elm.Native.String.make = function(elm) {
228245
229246 toInt: toInt,
230247 toFloat: toFloat,
248+ toList: toList,
249+ fromList: fromList,
231250 };
232251};
libraries/Random.elm+1−1
@@ -3,7 +3,7 @@ module Random where
33{-| Since the core of Elm is pure, randomness must be handled via signals.
44
55# Random Numbers
6−@docs range, float
6+@docs range, float, floatList
77-}
88
99import Signal (Signal)
libraries/Signal.elm+3−3
@@ -15,15 +15,15 @@ the [`Time`](/docs/Signal/Time.elm) library.
1515# Combine
1616@docs constant, lift, lift2, merge, merges, combine
1717
18−# Pretty Lift
19−@docs (<~), (~)
20−
2118# Past-Dependence
2219@docs foldp, count, countIf
2320
2421#Filters
2522@docs keepIf, dropIf, keepWhen, dropWhen, dropRepeats, sampleOn
2623
24+# Pretty Lift
25+@docs (<~), (~)
26+
2727# Do you even lift?
2828@docs lift3, lift4, lift5, lift6, lift7, lift8
2929
libraries/String.elm+45−8
@@ -3,11 +3,10 @@ module String where
33are enclosed in `"double quotes"`. Strings are *not* lists of characters.
44
55# Basics
6−@docs isEmpty, length, cons, uncons, reverse,
7− map, filter, foldl, foldr, any, all, repeat
6+@docs isEmpty, length, reverse, repeat
87
9−# Split and Join
10−@docs split, join, words, lines
8+# Building and Splitting
9+@docs cons, uncons, append, concat, split, join, words, lines
1110
1211# Get Substrings
1312@docs sub, left, right, dropLeft, dropRight
@@ -15,8 +14,8 @@ are enclosed in `"double quotes"`. Strings are *not* lists of characters.
1514# Check for Substrings
1615@docs contains, startsWith, endsWith, indexes, indices
1716
18−# Conversion To Numbers
19−@docs toInt, toFloat
17+# Conversions
18+@docs toInt, toFloat, toList, fromList
2019
2120# Formatting
2221Cosmetic operations such as padding with extra characters or trimming whitespace.
@@ -24,6 +23,9 @@ Cosmetic operations such as padding with extra characters or trimming whitespace
2423@docs toUpper, toLower,
2524 pad, padLeft, padRight,
2625 trim, trimLeft, trimRight
26+
27+# Higher-Order Functions
28+@docs map, filter, foldl, foldr, any, all
2729-}
2830
2931import Native.String
@@ -46,6 +48,21 @@ pattern match on strings exactly as you would with lists.
4648uncons : String -> Maybe (Char, String)
4749uncons = Native.String.uncons
4850
51+{-| Append two strings. You can also use [the `(++)` operator](/library/List.elm#++)
52+to do this.
53+
54+ append "butter" "fly" == "butterfly"
55+-}
56+append : String -> String -> String
57+append = Native.String.append
58+
59+{-| Concatenate many strings into one.
60+
61+ concat ["never","the","less"] == "nevertheless"
62+-}
63+concat : [String] -> String
64+concat = Native.String.concat
65+
4966{-| Get the length of a string `(length "innumerable" == 11)` -}
5067length : String -> Int
5168length = Native.String.length
@@ -68,12 +85,16 @@ filter = Native.String.filter
6885reverse : String -> String
6986reverse = Native.String.reverse
7087
71−{-|
88+{-| Reduce a string from the left:
89+
90+ foldl cons "" "time" == "emit"
7291-}
7392foldl : (Char -> b -> b) -> b -> String -> b
7493foldl = Native.String.foldl
7594
76−{-|
95+{-| Reduce a string from the right:
96+
97+ foldr cons "" "time" == "time"
7798-}
7899foldr : (Char -> b -> b) -> b -> String -> b
79100foldr = Native.String.foldr
@@ -272,3 +293,19 @@ toInt = Native.String.toInt
272293-}
273294toFloat : String -> Maybe Float
274295toFloat = Native.String.toFloat
296+
297+{-| Convert a string to a list of characters.
298+
299+ toList "abc" == ['a','b','c']
300+-}
301+toList : String -> [Char]
302+toList = Native.String.toList
303+
304+{-| Convert a list of characters into a String. Can be useful if you
305+want to create a string primarly by consing, perhaps for decoding
306+something.
307+
308+ fromList ['a','b','c'] == "abc"
309+-}
310+fromList : String -> [Char]
311+fromList = Native.String.fromList
runtime/Render/Utils.js+2−2
@@ -39,8 +39,8 @@ return {addTo:addTo,
3939 newElement:newElement,
4040 extract : extract,
4141 fromList: List.toArray,
42− fromString: function(s) { return List.toArray(s).join(''); },
43− toString: List.fromArray,
42+ fromString: function(s) { return s; },
43+ toString: function(s) { return s; },
4444 eq: Elm.Native.Utils.make({}).eq,
4545 addTransform: addTransform,
4646 removeTransform: removeTransform
server/elm-server.cabal+2−2
@@ -1,5 +1,5 @@
11Name: elm-server
2−Version: 0.9.0.2
2+Version: 0.10
33Synopsis: The Elm language server.
44Description: This package provides a standalone, Happstack-based Elm server.
55
@@ -36,5 +36,5 @@ Executable elm-server
3636 happstack-server,
3737 deepseq,
3838 filepath,
39− Elm >= 0.9.0.2,
39+ Elm >= 0.10,
4040 process