Skip to content

Commit 7bdd04c

Browse files
authored
Merge pull request #142 from purescript/compiler/0.12
Updates for 0.12
2 parents 8058d49 + da8e772 commit 7bdd04c

File tree

19 files changed

+522
-452
lines changed

19 files changed

+522
-452
lines changed

LICENSE

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
The MIT License (MIT)
1+
Copyright 2018 PureScript
22

3-
Copyright (c) 2014 PureScript
3+
Redistribution and use in source and binary forms, with or without modification,
4+
are permitted provided that the following conditions are met:
45

5-
Permission is hereby granted, free of charge, to any person obtaining a copy of
6-
this software and associated documentation files (the "Software"), to deal in
7-
the Software without restriction, including without limitation the rights to
8-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9-
the Software, and to permit persons to whom the Software is furnished to do so,
10-
subject to the following conditions:
6+
1. Redistributions of source code must retain the above copyright notice, this
7+
list of conditions and the following disclaimer.
118

12-
The above copyright notice and this permission notice shall be included in all
13-
copies or substantial portions of the Software.
9+
2. Redistributions in binary form must reproduce the above copyright notice,
10+
this list of conditions and the following disclaimer in the documentation and/or
11+
other materials provided with the distribution.
1412

15-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
3. Neither the name of the copyright holder nor the names of its contributors
14+
may be used to endorse or promote products derived from this software without
15+
specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

bower.json

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
{
22
"name": "purescript-arrays",
33
"homepage": "https://github.com/purescript/purescript-arrays",
4-
"description": "Array utility functions",
5-
"license": "MIT",
4+
"license": "BSD-3-Clause",
65
"repository": {
76
"type": "git",
87
"url": "git://github.com/purescript/purescript-arrays.git"
@@ -16,18 +15,22 @@
1615
"package.json"
1716
],
1817
"dependencies": {
19-
"purescript-foldable-traversable": "^3.3.0",
20-
"purescript-nonempty": "^4.0.0",
21-
"purescript-partial": "^1.2.0",
22-
"purescript-st": "^3.0.0",
23-
"purescript-tailrec": "^3.0.0",
24-
"purescript-tuples": "^4.0.0",
25-
"purescript-unfoldable": "^3.0.0",
26-
"purescript-unsafe-coerce": "^3.0.0"
18+
"purescript-bifunctors": "^4.0.0",
19+
"purescript-control": "^4.0.0",
20+
"purescript-foldable-traversable": "^4.0.0",
21+
"purescript-maybe": "^4.0.0",
22+
"purescript-nonempty": "^5.0.0",
23+
"purescript-partial": "^2.0.0",
24+
"purescript-prelude": "^4.0.0",
25+
"purescript-st": "^4.0.0",
26+
"purescript-tailrec": "^4.0.0",
27+
"purescript-tuples": "^5.0.0",
28+
"purescript-unfoldable": "^4.0.0",
29+
"purescript-unsafe-coerce": "^4.0.0"
2730
},
2831
"devDependencies": {
29-
"purescript-assert": "^3.0.0",
30-
"purescript-console": "^3.0.0",
31-
"purescript-const": "^3.0.0"
32+
"purescript-assert": "^4.0.0",
33+
"purescript-console": "^4.0.0",
34+
"purescript-const": "^4.0.0"
3235
}
3336
}

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
"test": "pulp test"
77
},
88
"devDependencies": {
9-
"eslint": "^3.17.1",
10-
"pulp": "^10.0.4",
11-
"purescript-psa": "^0.5.0-rc.1",
12-
"rimraf": "^2.6.1"
9+
"eslint": "^4.19.1",
10+
"pulp": "^12.2.0",
11+
"purescript-psa": "^0.6.0",
12+
"rimraf": "^2.6.2"
1313
}
1414
}

src/Data/Array.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ var replicatePolyfill = function (count) {
4040
};
4141

4242
// In browsers that have Array.prototype.fill we use it, as it's faster.
43-
exports.replicate = typeof Array.prototype.fill === "function" ?
44-
replicate :
45-
replicatePolyfill;
43+
exports.replicate = typeof Array.prototype.fill === "function" ? replicate : replicatePolyfill;
4644

4745
exports.fromFoldableImpl = (function () {
4846
function Cons(head, tail) {

src/Data/Array.purs

Lines changed: 90 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
-- | `Data.Foldable.or` tests whether an array of `Boolean` values contains
2626
-- | at least one `true` value.
2727
-- | * `Traversable`, which provides the PureScript version of a for-loop,
28-
-- | allowing you to iterate over an array and accumulate effects.
28+
-- | allowing you to STAI.iterate over an array and accumulate effects.
2929
-- |
3030
module Data.Array
3131
( fromFoldable
@@ -90,7 +90,9 @@ module Data.Array
9090
, groupBy
9191

9292
, nub
93+
, nubEq
9394
, nubBy
95+
, nubByEq
9496
, union
9597
, unionBy
9698
, delete
@@ -114,22 +116,24 @@ module Data.Array
114116
) where
115117

116118
import Prelude
119+
117120
import Control.Alt ((<|>))
118121
import Control.Alternative (class Alternative)
119122
import Control.Lazy (class Lazy, defer)
120123
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
121-
import Control.Monad.ST (pureST)
122-
import Data.Array.ST (unsafeFreeze, emptySTArray, pokeSTArray, pushSTArray, modifySTArray, withArray)
123-
import Data.Array.ST.Iterator (iterator, iterate, pushWhile)
124+
import Control.Monad.ST as ST
125+
import Data.Array.ST as STA
126+
import Data.Array.ST.Iterator as STAI
127+
import Data.Array.NonEmpty.Internal (NonEmptyArray)
124128
import Data.Foldable (class Foldable, foldl, foldr, traverse_)
125129
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
126130
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
127-
import Data.NonEmpty (NonEmpty, (:|))
128131
import Data.Traversable (scanl, scanr) as Exports
129132
import Data.Traversable (sequence, traverse)
130-
import Data.Tuple (Tuple(..), uncurry)
133+
import Data.Tuple (Tuple(..), fst, snd)
131134
import Data.Unfoldable (class Unfoldable, unfoldr)
132135
import Partial.Unsafe (unsafePartial)
136+
import Unsafe.Coerce (unsafeCoerce)
133137

134138
-- | Convert an `Array` into an `Unfoldable` structure.
135139
toUnfoldable :: forall f. Unfoldable f => Array ~> f
@@ -299,7 +303,7 @@ last xs = xs !! (length xs - 1)
299303
-- | `Nothing` if the array is empty
300304
-- |
301305
-- | ```purescript
302-
-- | tail [1, 2, 3, 4] = Just [2, 3, 4]
306+
-- | tail [1, 2, 3, 4] = Just [2, 3, 4]
303307
-- | tail [] = Nothing
304308
-- | ```
305309
-- |
@@ -348,7 +352,7 @@ foreign import uncons'
348352
-- | Break an array into its last element and all preceding elements.
349353
-- |
350354
-- | ```purescript
351-
-- | unsnoc [1, 2, 3] = Just {init: [1, 2], last: 3}
355+
-- | unsnoc [1, 2, 3] = Just {init: [1, 2], last: 3}
352356
-- | unsnoc [] = Nothing
353357
-- | ```
354358
-- |
@@ -511,7 +515,7 @@ foreign import _updateAt
511515
-- | array, or returning `Nothing` if the index is out of bounds.
512516
-- |
513517
-- | ```purescript
514-
-- | modifyAt 1 toUpper ["Hello", "World"] = Just ["Hello", "WORLD"]
518+
-- | modifyAt 1 toUpper ["Hello", "World"] = Just ["Hello", "WORLD"]
515519
-- | modifyAt 10 toUpper ["Hello", "World"] = Nothing
516520
-- | ```
517521
-- |
@@ -525,10 +529,10 @@ modifyAt i f xs = maybe Nothing go (xs !! i)
525529
-- | index is out-of-bounds.
526530
-- |
527531
-- | ```purescript
528-
-- | alterAt 1 (stripSuffix $ Pattern "!") ["Hello", "World!"]
532+
-- | alterAt 1 (stripSuffix $ Pattern "!") ["Hello", "World!"]
529533
-- | = Just ["Hello", "World"]
530534
-- |
531-
-- | alterAt 1 (stripSuffix $ Pattern "!!!!!") ["Hello", "World!"]
535+
-- | alterAt 1 (stripSuffix $ Pattern "!!!!!") ["Hello", "World!"]
532536
-- | = Just ["Hello"]
533537
-- |
534538
-- | alterAt 10 (stripSuffix $ Pattern "!") ["Hello", "World!"] = Nothing
@@ -629,7 +633,7 @@ mapMaybe f = concatMap (maybe [] singleton <<< f)
629633
-- | ```
630634
-- |
631635
catMaybes :: forall a. Array (Maybe a) -> Array a
632-
catMaybes = mapMaybe id
636+
catMaybes = mapMaybe identity
633637

634638
-- | Apply a function to each element in an array, supplying a generated
635639
-- | zero-based index integer along with the element, creating an array
@@ -656,7 +660,7 @@ mapWithIndex f xs =
656660
-- |
657661
updateAtIndices :: forall t a. Foldable t => t (Tuple Int a) -> Array a -> Array a
658662
updateAtIndices us xs =
659-
pureST (withArray (\res -> traverse_ (uncurry $ pokeSTArray res) us) xs)
663+
ST.run (STA.withArray (\res -> traverse_ (\(Tuple i a) -> STA.poke i a res) us) xs)
660664

661665
-- | Apply a function to the element at the specified indices,
662666
-- | creating a new array. Out-of-bounds indices will have no effect.
@@ -669,7 +673,7 @@ updateAtIndices us xs =
669673
-- |
670674
modifyAtIndices :: forall t a. Foldable t => t Int -> (a -> a) -> Array a -> Array a
671675
modifyAtIndices is f xs =
672-
pureST (withArray (\res -> traverse_ (\i -> modifySTArray res i f) is) xs)
676+
ST.run (STA.withArray (\res -> traverse_ (\i -> STA.modify i f res) is) xs)
673677

674678
--------------------------------------------------------------------------------
675679
-- Sorting ---------------------------------------------------------------------
@@ -836,15 +840,15 @@ span p arr =
836840
-- | ```purescript
837841
-- | group [1,1,2,2,1] == [NonEmpty 1 [1], NonEmpty 2 [2], NonEmpty 1 []]
838842
-- | ```
839-
group :: forall a. Eq a => Array a -> Array (NonEmpty Array a)
843+
group :: forall a. Eq a => Array a -> Array (NonEmptyArray a)
840844
group xs = groupBy eq xs
841845

842846
-- | Sort and then group the elements of an array into arrays.
843847
-- |
844848
-- | ```purescript
845849
-- | group' [1,1,2,2,1] == [NonEmpty 1 [1,1],NonEmpty 2 [2]]
846850
-- | ```
847-
group' :: forall a. Ord a => Array a -> Array (NonEmpty Array a)
851+
group' :: forall a. Ord a => Array a -> Array (NonEmptyArray a)
848852
group' = group <<< sort
849853

850854
-- | Group equal, consecutive elements of an array into arrays, using the
@@ -855,38 +859,75 @@ group' = group <<< sort
855859
-- | = [NonEmpty 1 [3], NonEmpty 2 [] , NonEmpty 4 [], NonEmpty 3 [3]]
856860
-- | ```
857861
-- |
858-
groupBy :: forall a. (a -> a -> Boolean) -> Array a -> Array (NonEmpty Array a)
862+
groupBy :: forall a. (a -> a -> Boolean) -> Array a -> Array (NonEmptyArray a)
859863
groupBy op xs =
860-
pureST do
861-
result <- emptySTArray
862-
iter <- iterator (xs !! _)
863-
iterate iter \x -> void do
864-
sub <- emptySTArray
865-
pushWhile (op x) iter sub
866-
sub_ <- unsafeFreeze sub
867-
pushSTArray result (x :| sub_)
868-
unsafeFreeze result
864+
ST.run do
865+
result <- STA.empty
866+
iter <- STAI.iterator (xs !! _)
867+
STAI.iterate iter \x -> void do
868+
sub <- STA.empty
869+
STAI.pushWhile (op x) iter sub
870+
_ <- STA.push x sub
871+
grp <- STA.unsafeFreeze sub
872+
STA.push ((unsafeCoerce :: Array ~> NonEmptyArray) grp) result
873+
STA.unsafeFreeze result
869874

870875
-- | Remove the duplicates from an array, creating a new array.
871876
-- |
872877
-- | ```purescript
873878
-- | nub [1, 2, 1, 3, 3] = [1, 2, 3]
874879
-- | ```
875880
-- |
876-
nub :: forall a. Eq a => Array a -> Array a
877-
nub = nubBy eq
881+
nub :: forall a. Ord a => Array a -> Array a
882+
nub = nubBy compare
883+
884+
-- | Remove the duplicates from an array, creating a new array.
885+
-- |
886+
-- | This less efficient version of `nub` only requires an `Eq` instance.
887+
-- |
888+
-- | ```purescript
889+
-- | nubEq [1, 2, 1, 3, 3] = [1, 2, 3]
890+
-- | ```
891+
-- |
892+
nubEq :: forall a. Eq a => Array a -> Array a
893+
nubEq = nubByEq eq
894+
895+
-- | Remove the duplicates from an array, where element equality is determined
896+
-- | by the specified ordering, creating a new array.
897+
-- |
898+
-- | ```purescript
899+
-- | nubBy compare [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
900+
-- | ```
901+
-- |
902+
nubBy :: forall a. (a -> a -> Ordering) -> Array a -> Array a
903+
nubBy comp xs = case head indexedAndSorted of
904+
Nothing -> []
905+
Just x -> map snd $ sortWith fst $ ST.run do
906+
-- TODO: use NonEmptyArrays here to avoid partial functions
907+
result <- STA.unsafeThaw $ singleton x
908+
ST.foreach indexedAndSorted \pair@(Tuple i x') -> do
909+
lst <- snd <<< unsafePartial (fromJust <<< last) <$> STA.unsafeFreeze result
910+
when (comp lst x' /= EQ) $ void $ STA.push pair result
911+
STA.unsafeFreeze result
912+
where
913+
indexedAndSorted :: Array (Tuple Int a)
914+
indexedAndSorted = sortBy (\x y -> comp (snd x) (snd y))
915+
(mapWithIndex Tuple xs)
878916

879917
-- | Remove the duplicates from an array, where element equality is determined
880918
-- | by the specified equivalence relation, creating a new array.
881919
-- |
920+
-- | This less efficient version of `nubBy` only requires an equivalence
921+
-- | relation.
922+
-- |
882923
-- | ```purescript
883-
-- | nubBy (\a b -> a `mod` 3 == b `mod` 3) [1, 3, 4, 5, 6] = [1,3,5]
924+
-- | nubByEq (\a b -> a `mod` 3 == b `mod` 3) [1, 3, 4, 5, 6] = [1,3,5]
884925
-- | ```
885926
-- |
886-
nubBy :: forall a. (a -> a -> Boolean) -> Array a -> Array a
887-
nubBy eq xs =
927+
nubByEq :: forall a. (a -> a -> Boolean) -> Array a -> Array a
928+
nubByEq eq xs =
888929
case uncons xs of
889-
Just o -> o.head : nubBy eq (filter (\y -> not (o.head `eq` y)) o.tail)
930+
Just o -> o.head : nubByEq eq (filter (\y -> not (o.head `eq` y)) o.tail)
890931
Nothing -> []
891932

892933
-- | Calculate the union of two arrays. Note that duplicates in the first array
@@ -911,7 +952,7 @@ union = unionBy (==)
911952
-- | ```
912953
-- |
913954
unionBy :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Array a
914-
unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubBy eq ys) xs
955+
unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubByEq eq ys) xs
915956

916957
-- | Delete the first element of an array which is equal to the specified value,
917958
-- | creating a new array.
@@ -1016,7 +1057,7 @@ zipWithA f xs ys = sequence (zipWith f xs ys)
10161057
-- | discarded.
10171058
-- |
10181059
-- | ```purescript
1019-
-- | zip [1, 2, 3] ["a", "b"] = [Tuple 1 "a", Tuple 2 "b"]
1060+
-- | zip [1, 2, 3] ["a", "b"] = [Tuple 1 "a", Tuple 2 "b"]
10201061
-- | ```
10211062
-- |
10221063
zip :: forall a b. Array a -> Array b -> Array (Tuple a b)
@@ -1031,15 +1072,15 @@ zip = zipWith Tuple
10311072
-- |
10321073
unzip :: forall a b. Array (Tuple a b) -> Tuple (Array a) (Array b)
10331074
unzip xs =
1034-
pureST do
1035-
fsts <- emptySTArray
1036-
snds <- emptySTArray
1037-
iter <- iterator (xs !! _)
1038-
iterate iter \(Tuple fst snd) -> do
1039-
void $ pushSTArray fsts fst
1040-
void $ pushSTArray snds snd
1041-
fsts' <- unsafeFreeze fsts
1042-
snds' <- unsafeFreeze snds
1075+
ST.run do
1076+
fsts <- STA.empty
1077+
snds <- STA.empty
1078+
iter <- STAI.iterator (xs !! _)
1079+
STAI.iterate iter \(Tuple fst snd) -> do
1080+
void $ STA.push fst fsts
1081+
void $ STA.push snd snds
1082+
fsts' <- STA.unsafeFreeze fsts
1083+
snds' <- STA.unsafeFreeze snds
10431084
pure $ Tuple fsts' snds'
10441085

10451086
-- | Perform a fold using a monadic step function.
@@ -1065,12 +1106,12 @@ foldRecM f a array = tailRecM2 go a 0
10651106
-- | ```purescript
10661107
-- | unsafePartial $ unsafeIndex ["a", "b", "c"] 1 = "b"
10671108
-- | ```
1068-
-- |
1069-
-- | Using `unsafeIndex` with an out-of-range index will not immediately raise a runtime error.
1070-
-- | Instead, the result will be undefined. Most attempts to subsequently use the result will
1071-
-- | cause a runtime error, of course, but this is not guaranteed, and is dependent on the backend;
1072-
-- | some programs will continue to run as if nothing is wrong. For example, in the JavaScript backend,
1073-
-- | the expression `unsafePartial (unsafeIndex [true] 1)` has type `Boolean`;
1109+
-- |
1110+
-- | Using `unsafeIndex` with an out-of-range index will not immediately raise a runtime error.
1111+
-- | Instead, the result will be undefined. Most attempts to subsequently use the result will
1112+
-- | cause a runtime error, of course, but this is not guaranteed, and is dependent on the backend;
1113+
-- | some programs will continue to run as if nothing is wrong. For example, in the JavaScript backend,
1114+
-- | the expression `unsafePartial (unsafeIndex [true] 1)` has type `Boolean`;
10741115
-- | since this expression evaluates to `undefined`, attempting to use it in an `if` statement will cause
10751116
-- | the else branch to be taken.
10761117
unsafeIndex :: forall a. Partial => Array a -> Int -> a

0 commit comments

Comments
 (0)