diff --git a/.travis.yml b/.travis.yml index 554955a..36183ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js -sudo: false -node_js: - - 4 +sudo: required +dist: trusty +node_js: 5 env: - PATH=$HOME/purescript:$PATH install: @@ -9,6 +9,16 @@ install: - wget -O $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz - tar -xvf $HOME/purescript.tar.gz -C $HOME/ - chmod a+x $HOME/purescript + - npm install -g bower - npm install + - bower install script: - npm run build +after_success: +- >- + test $TRAVIS_TAG && + psc-publish > .pursuit.json && + curl -X POST http://pursuit.purescript.org/packages \ + -d @.pursuit.json \ + -H 'Accept: application/json' \ + -H "Authorization: token ${GITHUB_TOKEN}" diff --git a/README.md b/README.md index c586520..5165890 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,6 @@ Some of this code is derived from GHC's standard libraries (`base`); according to its terms, we have included GHC's license in the file `LICENSE-GHC.md`. -## Module documentation +## Documentation -- [Data.List](docs/Data/List.md) -- [Data.List.Lazy](docs/Data/List/Lazy.md) -- [Data.List.Unsafe](docs/Data/List/Unsafe.md) -- [Data.List.ZipList](docs/Data/List/ZipList.md) +Module documentation is [published on Pursuit](http://pursuit.purescript.org/packages/purescript-lists). diff --git a/bower.json b/bower.json index 7142a40..0b0dbb3 100644 --- a/bower.json +++ b/bower.json @@ -5,9 +5,6 @@ "Phil Freeman " ], "description": "Linked lists", - "keywords": [ - "purescript" - ], "license": "MIT", "repository": { "type": "git", @@ -23,12 +20,12 @@ "package.json" ], "dependencies": { - "purescript-foldable-traversable": "^0.4.0", - "purescript-lazy": "^0.4.0", - "purescript-unfoldable": "^0.4.0" + "purescript-foldable-traversable": "^1.0.0-rc.1", + "purescript-lazy": "^1.0.0-rc.1", + "purescript-unfoldable": "^1.0.0-rc.1" }, "devDependencies": { - "purescript-assert": "^0.1.0", - "purescript-console": "^0.1.0" + "purescript-assert": "^1.0.0-rc.1", + "purescript-console": "^1.0.0-rc.1" } } diff --git a/docs/Data/List.md b/docs/Data/List.md deleted file mode 100644 index 930e2ca..0000000 --- a/docs/Data/List.md +++ /dev/null @@ -1,751 +0,0 @@ -## Module Data.List - -This module defines a type of _strict_ linked lists, and associated helper -functions and type class instances. - -_Note_: Depending on your use-case, you may prefer to use -`Data.Sequence` instead, which might give better performance for certain -use cases. This module is an improvement over `Data.Array` when working with -immutable lists of data in a purely-functional setting, but does not have -good random-access performance. - -#### `List` - -``` purescript -data List a - = Nil - | Cons a (List a) -``` - -A strict linked list. - -A list is either empty (represented by the `Nil` constructor) or non-empty, in -which case it consists of a head element, and another list (represented by the -`Cons` constructor). - -##### Instances -``` purescript -(Show a) => Show (List a) -(Eq a) => Eq (List a) -(Ord a) => Ord (List a) -Semigroup (List a) -Monoid (List a) -Functor List -Foldable List -Unfoldable List -Traversable List -Apply List -Applicative List -Bind List -Monad List -Alt List -Plus List -Alternative List -MonadPlus List -``` - -#### `toUnfoldable` - -``` purescript -toUnfoldable :: forall f a. (Unfoldable f) => List a -> f a -``` - -Convert a list into any unfoldable structure. - -Running time: `O(n)` - -#### `fromFoldable` - -``` purescript -fromFoldable :: forall f a. (Foldable f) => f a -> List a -``` - -Construct a list from a foldable structure. - -Running time: `O(n)` - -#### `singleton` - -``` purescript -singleton :: forall a. a -> List a -``` - -Create a list with a single element. - -Running time: `O(1)` - -#### `(..)` - -``` purescript -(..) :: Int -> Int -> List Int -``` - -_non-associative / precedence 8_ - -An infix synonym for `range`. - -#### `range` - -``` purescript -range :: Int -> Int -> List Int -``` - -Create a list containing a range of integers, including both endpoints. - -#### `replicate` - -``` purescript -replicate :: forall a. Int -> a -> List a -``` - -Create a list with repeated instances of a value. - -#### `replicateM` - -``` purescript -replicateM :: forall m a. (Monad m) => Int -> m a -> m (List a) -``` - -Perform a monadic action `n` times collecting all of the results. - -#### `some` - -``` purescript -some :: forall f a. (Alternative f, Lazy (f (List a))) => f a -> f (List a) -``` - -Attempt a computation multiple times, requiring at least one success. - -The `Lazy` constraint is used to generate the result lazily, to ensure -termination. - -#### `many` - -``` purescript -many :: forall f a. (Alternative f, Lazy (f (List a))) => f a -> f (List a) -``` - -Attempt a computation multiple times, returning as many successful results -as possible (possibly zero). - -The `Lazy` constraint is used to generate the result lazily, to ensure -termination. - -#### `null` - -``` purescript -null :: forall a. List a -> Boolean -``` - -Test whether a list is empty. - -Running time: `O(1)` - -#### `length` - -``` purescript -length :: forall a. List a -> Int -``` - -Get the length of a list - -Running time: `O(n)` - -#### `(:)` - -``` purescript -(:) :: forall a. a -> List a -> List a -``` - -_right-associative / precedence 6_ - -An infix alias for `Cons`; attaches an element to the front of -a list. - -Running time: `O(1)` - -#### `snoc` - -``` purescript -snoc :: forall a. List a -> a -> List a -``` - -Append an element to the end of an array, creating a new array. - -Running time: `O(2n)` - -#### `insert` - -``` purescript -insert :: forall a. (Ord a) => a -> List a -> List a -``` - -Insert an element into a sorted list. - -Running time: `O(n)` - -#### `insertBy` - -``` purescript -insertBy :: forall a. (a -> a -> Ordering) -> a -> List a -> List a -``` - -Insert an element into a sorted list, using the specified function to -determine the ordering of elements. - -Running time: `O(n)` - -#### `head` - -``` purescript -head :: forall a. List a -> Maybe a -``` - -Get the first element in a list, or `Nothing` if the list is empty. - -Running time: `O(1)`. - -#### `last` - -``` purescript -last :: forall a. List a -> Maybe a -``` - -Get the last element in a list, or `Nothing` if the list is empty. - -Running time: `O(n)`. - -#### `tail` - -``` purescript -tail :: forall a. List a -> Maybe (List a) -``` - -Get all but the first element of a list, or `Nothing` if the list is empty. - -Running time: `O(1)` - -#### `init` - -``` purescript -init :: forall a. List a -> Maybe (List a) -``` - -Get all but the last element of a list, or `Nothing` if the list is empty. - -Running time: `O(n)` - -#### `uncons` - -``` purescript -uncons :: forall a. List a -> Maybe { head :: a, tail :: List a } -``` - -Break a list into its first element, and the remaining elements, -or `Nothing` if the list is empty. - -Running time: `O(1)` - -#### `index` - -``` purescript -index :: forall a. List a -> Int -> Maybe a -``` - -Get the element at the specified index, or `Nothing` if the index is out-of-bounds. - -Running time: `O(n)` where `n` is the required index. - -#### `(!!)` - -``` purescript -(!!) :: forall a. List a -> Int -> Maybe a -``` - -_left-associative / precedence 8_ - -An infix synonym for `index`. - -#### `elemIndex` - -``` purescript -elemIndex :: forall a. (Eq a) => a -> List a -> Maybe Int -``` - -Find the index of the first element equal to the specified element. - -#### `elemLastIndex` - -``` purescript -elemLastIndex :: forall a. (Eq a) => a -> List a -> Maybe Int -``` - -Find the index of the last element equal to the specified element. - -#### `findIndex` - -``` purescript -findIndex :: forall a. (a -> Boolean) -> List a -> Maybe Int -``` - -Find the first index for which a predicate holds. - -#### `findLastIndex` - -``` purescript -findLastIndex :: forall a. (a -> Boolean) -> List a -> Maybe Int -``` - -Find the last index for which a predicate holds. - -#### `insertAt` - -``` purescript -insertAt :: forall a. Int -> a -> List a -> Maybe (List a) -``` - -Insert an element into a list at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -Running time: `O(n)` - -#### `deleteAt` - -``` purescript -deleteAt :: forall a. Int -> List a -> Maybe (List a) -``` - -Delete an element from a list at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -Running time: `O(n)` - -#### `updateAt` - -``` purescript -updateAt :: forall a. Int -> a -> List a -> Maybe (List a) -``` - -Update the element at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -Running time: `O(n)` - -#### `modifyAt` - -``` purescript -modifyAt :: forall a. Int -> (a -> a) -> List a -> Maybe (List a) -``` - -Update the element at the specified index by applying a function to -the current value, returning a new list or `Nothing` if the index is -out-of-bounds. - -Running time: `O(n)` - -#### `alterAt` - -``` purescript -alterAt :: forall a. Int -> (a -> Maybe a) -> List a -> Maybe (List a) -``` - -Update or delete the element at the specified index by applying a -function to the current value, returning a new list or `Nothing` if the -index is out-of-bounds. - -Running time: `O(n)` - -#### `reverse` - -``` purescript -reverse :: forall a. List a -> List a -``` - -Reverse a list. - -Running time: `O(n)` - -#### `concat` - -``` purescript -concat :: forall a. List (List a) -> List a -``` - -Flatten a list of lists. - -Running time: `O(n)`, where `n` is the total number of elements. - -#### `concatMap` - -``` purescript -concatMap :: forall a b. (a -> List b) -> List a -> List b -``` - -Apply a function to each element in a list, and flatten the results -into a single, new list. - -Running time: `O(n)`, where `n` is the total number of elements. - -#### `filter` - -``` purescript -filter :: forall a. (a -> Boolean) -> List a -> List a -``` - -Filter a list, keeping the elements which satisfy a predicate function. - -Running time: `O(n)` - -#### `filterM` - -``` purescript -filterM :: forall a m. (Monad m) => (a -> m Boolean) -> List a -> m (List a) -``` - -Filter where the predicate returns a monadic `Boolean`. - -For example: - -```purescript -powerSet :: forall a. [a] -> [[a]] -powerSet = filterM (const [true, false]) -``` - -#### `mapMaybe` - -``` purescript -mapMaybe :: forall a b. (a -> Maybe b) -> List a -> List b -``` - -Apply a function to each element in a list, keeping only the results which -contain a value. - -Running time: `O(n)` - -#### `catMaybes` - -``` purescript -catMaybes :: forall a. List (Maybe a) -> List a -``` - -Filter a list of optional values, keeping only the elements which contain -a value. - -#### `mapWithIndex` - -``` purescript -mapWithIndex :: forall a b. (a -> Int -> b) -> List a -> List b -``` - -Apply a function to each element and its index in a list starting at 0. - -#### `sort` - -``` purescript -sort :: forall a. (Ord a) => List a -> List a -``` - -Sort the elements of an list in increasing order. - -#### `sortBy` - -``` purescript -sortBy :: forall a. (a -> a -> Ordering) -> List a -> List a -``` - -Sort the elements of a list in increasing order, where elements are -compared using the specified ordering. - -#### `slice` - -``` purescript -slice :: forall a. Int -> Int -> List a -> List a -``` - -Extract a sublist by a start and end index. - -#### `take` - -``` purescript -take :: forall a. Int -> List a -> List a -``` - -Take the specified number of elements from the front of a list. - -Running time: `O(n)` where `n` is the number of elements to take. - -#### `takeWhile` - -``` purescript -takeWhile :: forall a. (a -> Boolean) -> List a -> List a -``` - -Take those elements from the front of a list which match a predicate. - -Running time (worst case): `O(n)` - -#### `drop` - -``` purescript -drop :: forall a. Int -> List a -> List a -``` - -Drop the specified number of elements from the front of a list. - -Running time: `O(n)` where `n` is the number of elements to drop. - -#### `dropWhile` - -``` purescript -dropWhile :: forall a. (a -> Boolean) -> List a -> List a -``` - -Drop those elements from the front of a list which match a predicate. - -Running time (worst case): `O(n)` - -#### `span` - -``` purescript -span :: forall a. (a -> Boolean) -> List a -> { init :: List a, rest :: List a } -``` - -Split a list into two parts: - -1. the longest initial segment for which all elements satisfy the specified predicate -2. the remaining elements - -For example, - -```purescript -span (\n -> n % 2 == 1) (1 : 3 : 2 : 4 : 5 : Nil) == { init: (1 : 3 : Nil), rest: (2 : 4 : 5 : Nil) } -``` - -Running time: `O(n)` - -#### `group` - -``` purescript -group :: forall a. (Eq a) => List a -> List (List a) -``` - -Group equal, consecutive elements of a list into lists. - -For example, - -```purescript -group (1 : 1 : 2 : 2 : 1 : Nil) == (1 : 1 : Nil) : (2 : 2 : Nil) : (1 : Nil) : Nil -``` - -Running time: `O(n)` - -#### `group'` - -``` purescript -group' :: forall a. (Ord a) => List a -> List (List a) -``` - -Sort and then group the elements of a list into lists. - -```purescript -group' [1,1,2,2,1] == [[1,1,1],[2,2]] -``` - -#### `groupBy` - -``` purescript -groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (List a) -``` - -Group equal, consecutive elements of a list into lists, using the specified -equivalence relation to determine equality. - -Running time: `O(n)` - -#### `nub` - -``` purescript -nub :: forall a. (Eq a) => List a -> List a -``` - -Remove duplicate elements from a list. - -Running time: `O(n^2)` - -#### `nubBy` - -``` purescript -nubBy :: forall a. (a -> a -> Boolean) -> List a -> List a -``` - -Remove duplicate elements from a list, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `union` - -``` purescript -union :: forall a. (Eq a) => List a -> List a -> List a -``` - -Calculate the union of two lists. - -Running time: `O(n^2)` - -#### `unionBy` - -``` purescript -unionBy :: forall a. (a -> a -> Boolean) -> List a -> List a -> List a -``` - -Calculate the union of two lists, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `delete` - -``` purescript -delete :: forall a. (Eq a) => a -> List a -> List a -``` - -Delete the first occurrence of an element from a list. - -Running time: `O(n)` - -#### `deleteBy` - -``` purescript -deleteBy :: forall a. (a -> a -> Boolean) -> a -> List a -> List a -``` - -Delete the first occurrence of an element from a list, using the specified -function to determine equality of elements. - -Running time: `O(n)` - -#### `(\\)` - -``` purescript -(\\) :: forall a. (Eq a) => List a -> List a -> List a -``` - -_non-associative / precedence 5_ - -Delete the first occurrence of each element in the second list from the first list. - -Running time: `O(n^2)` - -#### `intersect` - -``` purescript -intersect :: forall a. (Eq a) => List a -> List a -> List a -``` - -Calculate the intersection of two lists. - -Running time: `O(n^2)` - -#### `intersectBy` - -``` purescript -intersectBy :: forall a. (a -> a -> Boolean) -> List a -> List a -> List a -``` - -Calculate the intersection of two lists, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `zipWith` - -``` purescript -zipWith :: forall a b c. (a -> b -> c) -> List a -> List b -> List c -``` - -Apply a function to pairs of elements at the same positions in two lists, -collecting the results in a new list. - -If one list is longer, elements will be discarded from the longer list. - -For example - -```purescript -zipWith (*) (1 : 2 : 3 : Nil) (4 : 5 : 6 : 7 Nil) == 4 : 10 : 18 : Nil -``` - -Running time: `O(min(m, n))` - -#### `zipWithA` - -``` purescript -zipWithA :: forall m a b c. (Applicative m) => (a -> b -> m c) -> List a -> List b -> m (List c) -``` - -A generalization of `zipWith` which accumulates results in some `Applicative` -functor. - -#### `zip` - -``` purescript -zip :: forall a b. List a -> List b -> List (Tuple a b) -``` - -Collect pairs of elements at the same positions in two lists. - -Running time: `O(min(m, n))` - -#### `unzip` - -``` purescript -unzip :: forall a b. List (Tuple a b) -> Tuple (List a) (List b) -``` - -Transforms a list of pairs into a list of first components and a list of -second components. - -#### `transpose` - -``` purescript -transpose :: forall a. List (List a) -> List (List a) -``` - -The 'transpose' function transposes the rows and columns of its argument. -For example, - - transpose ((1:2:3:Nil) : (4:5:6:Nil) : Nil) == - ((1:4:Nil) : (2:5:Nil) : (3:6:Nil) : Nil) - -If some of the rows are shorter than the following rows, their elements are skipped: - - transpose ((10:11:Nil) : (20:Nil) : Nil : (30:31:32:Nil) : Nil) == - ((10:20:30:Nil) : (11:31:Nil) : (32:Nil) : Nil) - -#### `foldM` - -``` purescript -foldM :: forall m a b. (Monad m) => (a -> b -> m a) -> a -> List b -> m a -``` - -Perform a fold using a monadic step function. - -#### `toList` - -``` purescript -toList :: forall f a. (Foldable f) => f a -> List a -``` - -*Deprecated.* Use `fromFoldable` instead. `toList` will be removed in a -later version. - -#### `fromList` - -``` purescript -fromList :: forall f a. (Unfoldable f) => List a -> f a -``` - -*Deprecated.* Use `toUnfoldable` instead. `fromList` will be removed in a -later version. - - diff --git a/docs/Data/List/Lazy.md b/docs/Data/List/Lazy.md deleted file mode 100644 index f382364..0000000 --- a/docs/Data/List/Lazy.md +++ /dev/null @@ -1,667 +0,0 @@ -## Module Data.List.Lazy - -This module defines a type of _lazy_ linked lists, and associated helper -functions and type class instances. - -_Note_: Depending on your use-case, you may prefer to use -`Data.Sequence` instead, which might give better performance for certain -use cases. This module is an improvement over `Data.Array` when working with -immutable lists of data in a purely-functional setting, but does not have -good random-access performance. - -#### `List` - -``` purescript -newtype List a - = List (Lazy (Step a)) -``` - -A lazy linked list. - -##### Instances -``` purescript -(Show a) => Show (List a) -(Eq a) => Eq (List a) -(Ord a) => Ord (List a) -Lazy (List a) -Semigroup (List a) -Monoid (List a) -Functor List -Foldable List -Unfoldable List -Traversable List -Apply List -Applicative List -Bind List -Monad List -Alt List -Plus List -Alternative List -MonadPlus List -``` - -#### `runList` - -``` purescript -runList :: forall a. List a -> Lazy (Step a) -``` - -Unwrap a lazy linked list - -#### `toUnfoldable` - -``` purescript -toUnfoldable :: forall f a. (Unfoldable f) => List a -> f a -``` - -Convert a list into any unfoldable structure. - -Running time: `O(n)` - -#### `fromFoldable` - -``` purescript -fromFoldable :: forall f a. (Foldable f) => f a -> List a -``` - -Construct a list from a foldable structure. - -Running time: `O(n)` - -#### `Step` - -``` purescript -data Step a - = Nil - | Cons a (List a) -``` - -A list is either empty (represented by the `Nil` constructor) or non-empty, in -which case it consists of a head element, and another list (represented by the -`Cons` constructor). - -#### `step` - -``` purescript -step :: forall a. List a -> Step a -``` - -Unwrap a lazy linked list - -#### `nil` - -``` purescript -nil :: forall a. List a -``` - -The empty list. - -Running time: `O(1)` - -#### `singleton` - -``` purescript -singleton :: forall a. a -> List a -``` - -Create a list with a single element. - -Running time: `O(1)` - -#### `(..)` - -``` purescript -(..) :: Int -> Int -> List Int -``` - -_left-associative / precedence -1_ - -An infix synonym for `range`. - -#### `range` - -``` purescript -range :: Int -> Int -> List Int -``` - -Create a list containing a range of integers, including both endpoints. - -#### `repeat` - -``` purescript -repeat :: forall a. a -> List a -``` - -Create a list by repeating an element - -#### `iterate` - -``` purescript -iterate :: forall a. (a -> a) -> a -> List a -``` - -Create a list by iterating a function - -#### `cycle` - -``` purescript -cycle :: forall a. List a -> List a -``` - -Create a list by repeating another list - -#### `null` - -``` purescript -null :: forall a. List a -> Boolean -``` - -Test whether a list is empty. - -Running time: `O(1)` - -#### `length` - -``` purescript -length :: forall a. List a -> Int -``` - -Get the length of a list - -Running time: `O(n)` - -#### `cons` - -``` purescript -cons :: forall a. a -> List a -> List a -``` - -Attach an element to the front of a lazy list. - -Running time: `O(1)` - -#### `(:)` - -``` purescript -(:) :: forall a. a -> List a -> List a -``` - -_right-associative / precedence 6_ - -An infix alias for `cons`; attaches an element to the front of -a list. - -Running time: `O(1)` - -#### `insert` - -``` purescript -insert :: forall a. (Ord a) => a -> List a -> List a -``` - -Insert an element into a sorted list. - -Running time: `O(n)` - -#### `insertBy` - -``` purescript -insertBy :: forall a. (a -> a -> Ordering) -> a -> List a -> List a -``` - -Insert an element into a sorted list, using the specified function to determine the ordering -of elements. - -Running time: `O(n)` - -#### `head` - -``` purescript -head :: forall a. List a -> Maybe a -``` - -Get the first element in a list, or `Nothing` if the list is empty. - -Running time: `O(1)`. - -#### `last` - -``` purescript -last :: forall a. List a -> Maybe a -``` - -Get the last element in a list, or `Nothing` if the list is empty. - -Running time: `O(n)`. - -#### `tail` - -``` purescript -tail :: forall a. List a -> Maybe (List a) -``` - -Get all but the first element of a list, or `Nothing` if the list is empty. - -Running time: `O(1)` - -#### `init` - -``` purescript -init :: forall a. List a -> Maybe (List a) -``` - -Get all but the last element of a list, or `Nothing` if the list is empty. - -Running time: `O(n)` - -#### `uncons` - -``` purescript -uncons :: forall a. List a -> Maybe { head :: a, tail :: List a } -``` - -Break a list into its first element, and the remaining elements, -or `Nothing` if the list is empty. - -Running time: `O(1)` - -#### `index` - -``` purescript -index :: forall a. List a -> Int -> Maybe a -``` - -Get the element at the specified index, or `Nothing` if the index is out-of-bounds. - -Running time: `O(n)` where `n` is the required index. - -#### `(!!)` - -``` purescript -(!!) :: forall a. List a -> Int -> Maybe a -``` - -_left-associative / precedence 8_ - -An infix synonym for `index`. - -#### `insertAt` - -``` purescript -insertAt :: forall a. Int -> a -> List a -> List a -``` - -Insert an element into a list at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -This function differs from the strict equivalent in that out-of-bounds arguments -result in the element being appended at the _end_ of the list. - -Running time: `O(n)` - -#### `deleteAt` - -``` purescript -deleteAt :: forall a. Int -> List a -> List a -``` - -Delete an element from a list at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -This function differs from the strict equivalent in that out-of-bounds arguments -result in the original list being returned unchanged. - -Running time: `O(n)` - -#### `updateAt` - -``` purescript -updateAt :: forall a. Int -> a -> List a -> List a -``` - -Update the element at the specified index, returning a new -list or `Nothing` if the index is out-of-bounds. - -This function differs from the strict equivalent in that out-of-bounds arguments -result in the original list being returned unchanged. - -Running time: `O(n)` - -#### `modifyAt` - -``` purescript -modifyAt :: forall a. Int -> (a -> a) -> List a -> List a -``` - -Update the element at the specified index by applying a function to -the current value, returning a new list or `Nothing` if the index is -out-of-bounds. - -This function differs from the strict equivalent in that out-of-bounds arguments -result in the original list being returned unchanged. - -Running time: `O(n)` - -#### `alterAt` - -``` purescript -alterAt :: forall a. Int -> (a -> Maybe a) -> List a -> List a -``` - -Update or delete the element at the specified index by applying a -function to the current value, returning a new list or `Nothing` if the -index is out-of-bounds. - -This function differs from the strict equivalent in that out-of-bounds arguments -result in the original list being returned unchanged. - -Running time: `O(n)` - -#### `reverse` - -``` purescript -reverse :: forall a. List a -> List a -``` - -Reverse a list. - -Running time: `O(n)` - -#### `concat` - -``` purescript -concat :: forall a. List (List a) -> List a -``` - -Flatten a list of lists. - -Running time: `O(n)`, where `n` is the total number of elements. - -#### `concatMap` - -``` purescript -concatMap :: forall a b. (a -> List b) -> List a -> List b -``` - -Apply a function to each element in a list, and flatten the results -into a single, new list. - -Running time: `O(n)`, where `n` is the total number of elements. - -#### `filter` - -``` purescript -filter :: forall a. (a -> Boolean) -> List a -> List a -``` - -Filter a list, keeping the elements which satisfy a predicate function. - -Running time: `O(n)` - -#### `mapMaybe` - -``` purescript -mapMaybe :: forall a b. (a -> Maybe b) -> List a -> List b -``` - -Apply a function to each element in a list, keeping only the results which -contain a value. - -Running time: `O(n)` - -#### `catMaybes` - -``` purescript -catMaybes :: forall a. List (Maybe a) -> List a -``` - -Filter a list of optional values, keeping only the elements which contain -a value. - -#### `take` - -``` purescript -take :: forall a. Int -> List a -> List a -``` - -Take the specified number of elements from the front of a list. - -Running time: `O(n)` where `n` is the number of elements to take. - -#### `takeWhile` - -``` purescript -takeWhile :: forall a. (a -> Boolean) -> List a -> List a -``` - -Take those elements from the front of a list which match a predicate. - -Running time (worst case): `O(n)` - -#### `drop` - -``` purescript -drop :: forall a. Int -> List a -> List a -``` - -Drop the specified number of elements from the front of a list. - -Running time: `O(n)` where `n` is the number of elements to drop. - -#### `dropWhile` - -``` purescript -dropWhile :: forall a. (a -> Boolean) -> List a -> List a -``` - -Drop those elements from the front of a list which match a predicate. - -Running time (worst case): `O(n)` - -#### `span` - -``` purescript -span :: forall a. (a -> Boolean) -> List a -> { init :: List a, rest :: List a } -``` - -Split a list into two parts: - -1. the longest initial segment for which all elements satisfy the specified predicate -2. the remaining elements - -For example, - -```purescript -span (\n -> n % 2 == 1) (1 : 3 : 2 : 4 : 5 : Nil) == Tuple (1 : 3 : Nil) (2 : 4 : 5 : Nil) -``` - -Running time: `O(n)` - -#### `group` - -``` purescript -group :: forall a. (Eq a) => List a -> List (List a) -``` - -Group equal, consecutive elements of a list into lists. - -For example, - -```purescript -group (1 : 1 : 2 : 2 : 1 : Nil) == (1 : 1 : Nil) : (2 : 2 : Nil) : (1 : Nil) : Nil -``` - -Running time: `O(n)` - -#### `groupBy` - -``` purescript -groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (List a) -``` - -Group equal, consecutive elements of a list into lists, using the specified -equivalence relation to determine equality. - -Running time: `O(n)` - -#### `nub` - -``` purescript -nub :: forall a. (Eq a) => List a -> List a -``` - -Remove duplicate elements from a list. - -Running time: `O(n^2)` - -#### `nubBy` - -``` purescript -nubBy :: forall a. (a -> a -> Boolean) -> List a -> List a -``` - -Remove duplicate elements from a list, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `union` - -``` purescript -union :: forall a. (Eq a) => List a -> List a -> List a -``` - -Calculate the union of two lists. - -Running time: `O(n^2)` - -#### `unionBy` - -``` purescript -unionBy :: forall a. (a -> a -> Boolean) -> List a -> List a -> List a -``` - -Calculate the union of two lists, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `delete` - -``` purescript -delete :: forall a. (Eq a) => a -> List a -> List a -``` - -Delete the first occurrence of an element from a list. - -Running time: `O(n)` - -#### `deleteBy` - -``` purescript -deleteBy :: forall a. (a -> a -> Boolean) -> a -> List a -> List a -``` - -Delete the first occurrence of an element from a list, using the specified -function to determine equality of elements. - -Running time: `O(n)` - -#### `(\\)` - -``` purescript -(\\) :: forall a. (Eq a) => List a -> List a -> List a -``` - -_non-associative / precedence 5_ - -Delete the first occurrence of each element in the second list from the first list. - -Running time: `O(n^2)` - -#### `intersect` - -``` purescript -intersect :: forall a. (Eq a) => List a -> List a -> List a -``` - -Calculate the intersection of two lists. - -Running time: `O(n^2)` - -#### `intersectBy` - -``` purescript -intersectBy :: forall a. (a -> a -> Boolean) -> List a -> List a -> List a -``` - -Calculate the intersection of two lists, using the specified -function to determine equality of elements. - -Running time: `O(n^2)` - -#### `zipWith` - -``` purescript -zipWith :: forall a b c. (a -> b -> c) -> List a -> List b -> List c -``` - -Apply a function to pairs of elements at the same positions in two lists, -collecting the results in a new list. - -If one list is longer, elements will be discarded from the longer list. - -For example - -```purescript -zipWith (*) (1 : 2 : 3 : Nil) (4 : 5 : 6 : 7 Nil) == 4 : 10 : 18 : Nil -``` - -Running time: `O(min(m, n))` - -#### `zip` - -``` purescript -zip :: forall a b. List a -> List b -> List (Tuple a b) -``` - -Collect pairs of elements at the same positions in two lists. - -Running time: `O(min(m, n))` - -#### `transpose` - -``` purescript -transpose :: forall a. List (List a) -> List (List a) -``` - -The 'transpose' function transposes the rows and columns of its argument. -For example, - - transpose ((1:2:3:nil) : (4:5:6:nil) : nil) == - ((1:4:nil) : (2:5:nil) : (3:6:nil) : nil) - -If some of the rows are shorter than the following rows, their elements are skipped: - - transpose ((10:11:nil) : (20:nil) : nil : (30:31:32:nil) : nil) == - ((10:20:30:nil) : (11:31:nil) : (32:nil) : nil) - -#### `toList` - -``` purescript -toList :: forall f a. (Foldable f) => f a -> List a -``` - -*Deprecated.* Use `fromFoldable` instead. `toList` will be removed in a -later version. - -#### `fromList` - -``` purescript -fromList :: forall f a. (Unfoldable f) => List a -> f a -``` - -*Deprecated.* Use `toUnfoldable` instead. `fromList` will be removed in a -later version. - - diff --git a/docs/Data/List/Unsafe.md b/docs/Data/List/Unsafe.md deleted file mode 100644 index cea14d3..0000000 --- a/docs/Data/List/Unsafe.md +++ /dev/null @@ -1,48 +0,0 @@ -## Module Data.List.Unsafe - -Unsafe helper functions for working with strict linked lists. - -_Note_: these functions should be used with care, and may result in unspecified -behavior, including runtime exceptions. - -#### `head` - -``` purescript -head :: forall a. List a -> a -``` - -Get the first element of a non-empty list. - -Running time: `O(1)`. - -#### `tail` - -``` purescript -tail :: forall a. List a -> List a -``` - -Get all but the first element of a non-empty list. - -Running time: `O(1)` - -#### `last` - -``` purescript -last :: forall a. List a -> a -``` - -Get the last element of a non-empty list. - -Running time: `O(n)` - -#### `init` - -``` purescript -init :: forall a. List a -> List a -``` - -Get all but the last element of a non-empty list. - -Running time: `O(n)` - - diff --git a/docs/Data/List/ZipList.md b/docs/Data/List/ZipList.md deleted file mode 100644 index 4c62960..0000000 --- a/docs/Data/List/ZipList.md +++ /dev/null @@ -1,41 +0,0 @@ -## Module Data.List.ZipList - -This module defines the type of _zip lists_, i.e. linked lists -with a zippy `Applicative` instance. - -#### `ZipList` - -``` purescript -newtype ZipList a - = ZipList (List a) -``` - -`ZipList` is a newtype around `List` which provides a zippy -`Applicative` instance. - -##### Instances -``` purescript -(Show a) => Show (ZipList a) -(Eq a) => Eq (ZipList a) -(Ord a) => Ord (ZipList a) -Semigroup (ZipList a) -Monoid (ZipList a) -Foldable ZipList -Traversable ZipList -Functor ZipList -Apply ZipList -Applicative ZipList -Alt ZipList -Plus ZipList -Alternative ZipList -``` - -#### `runZipList` - -``` purescript -runZipList :: forall a. ZipList a -> List a -``` - -Unpack a `ZipList` to obtain the underlying list. - - diff --git a/package.json b/package.json index c00fad1..01e1472 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "private": true, "scripts": { - "postinstall": "pulp dep install", - "build": "pulp test && rimraf docs && pulp docs" + "clean": "rimraf output && rimraf .pulp-cache", + "build": "pulp build", + "test": "pulp test" }, "devDependencies": { - "pulp": "^4.0.2", - "rimraf": "^2.4.1" + "pulp": "^8.1.0", + "rimraf": "^2.5.0" } } diff --git a/src/Data/List.purs b/src/Data/List.purs index 2b42c0c..21b77c8 100644 --- a/src/Data/List.purs +++ b/src/Data/List.purs @@ -84,17 +84,15 @@ module Data.List , transpose , foldM - - , toList - , fromList ) where -import Prelude (class Monad, class Bind, class Applicative, class Apply, class Functor, class Semigroup, class Ord, class Eq, class Show, Ordering(EQ, GT, LT), append, flip, (<*>), (<$>), (<>), pure, (<<<), ($), compare, (==), (&&), show, (++), (>>=), return, not, eq, (-), otherwise, (/=), id, bind, (+), one, (<), (<=), negate, (>)) +import Prelude import Control.Alt (class Alt, (<|>)) import Control.Alternative (class Alternative) import Control.Lazy (class Lazy, defer) import Control.MonadPlus (class MonadPlus) +import Control.MonadZero (class MonadZero) import Control.Plus (class Plus) import Data.Foldable (class Foldable, foldl, foldr, any) @@ -114,13 +112,13 @@ data List a = Nil | Cons a (List a) -- | Convert a list into any unfoldable structure. -- | -- | Running time: `O(n)` -toUnfoldable :: forall f a. (Unfoldable f) => List a -> f a +toUnfoldable :: forall f a. Unfoldable f => List a -> f a toUnfoldable = unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> uncons xs) -- | Construct a list from a foldable structure. -- | -- | Running time: `O(n)` -fromFoldable :: forall f a. (Foldable f) => f a -> List a +fromFoldable :: forall f a. Foldable f => f a -> List a fromFoldable = foldr Cons Nil -------------------------------------------------------------------------------- @@ -152,11 +150,13 @@ replicate n value = go n Nil | otherwise = go (n - 1) (Cons value rest) -- | Perform a monadic action `n` times collecting all of the results. -replicateM :: forall m a. (Monad m) => Int -> m a -> m (List a) -replicateM n m | n < one = return Nil - | otherwise = do a <- m - as <- replicateM (n - one) m - return (Cons a as) +replicateM :: forall m a. Monad m => Int -> m a -> m (List a) +replicateM n m + | n < one = pure Nil + | otherwise = do + a <- m + as <- replicateM (n - one) m + pure (Cons a as) -- | Attempt a computation multiple times, requiring at least one success. -- | @@ -209,7 +209,7 @@ snoc xs x = reverse (Cons x (reverse xs)) -- | Insert an element into a sorted list. -- | -- | Running time: `O(n)` -insert :: forall a. (Ord a) => a -> List a -> List a +insert :: forall a. Ord a => a -> List a -> List a insert = insertBy compare -- | Insert an element into a sorted list, using the specified function to @@ -284,11 +284,11 @@ index (Cons _ as) i = index as (i - 1) infixl 8 index as !! -- | Find the index of the first element equal to the specified element. -elemIndex :: forall a. (Eq a) => a -> List a -> Maybe Int +elemIndex :: forall a. Eq a => a -> List a -> Maybe Int elemIndex x = findIndex (_ == x) -- | Find the index of the last element equal to the specified element. -elemLastIndex :: forall a. (Eq a) => a -> List a -> Maybe Int +elemLastIndex :: forall a. Eq a => a -> List a -> Maybe Int elemLastIndex x = findLastIndex (_ == x) -- | Find the first index for which a predicate holds. @@ -398,14 +398,12 @@ filter p = go Nil -- | powerSet :: forall a. [a] -> [[a]] -- | powerSet = filterM (const [true, false]) -- | ``` -filterM :: forall a m. (Monad m) => (a -> m Boolean) -> List a -> m (List a) -filterM _ Nil = return Nil +filterM :: forall a m. Monad m => (a -> m Boolean) -> List a -> m (List a) +filterM _ Nil = pure Nil filterM p (Cons x xs) = do b <- p x xs' <- filterM p xs - return $ if b - then Cons x xs' - else xs' + pure if b then Cons x xs' else xs' -- | Apply a function to each element in a list, keeping only the results which -- | contain a value. @@ -438,7 +436,7 @@ mapWithIndex f lst = reverse $ go 0 lst Nil -------------------------------------------------------------------------------- -- | Sort the elements of an list in increasing order. -sort :: forall a. (Ord a) => List a -> List a +sort :: forall a. Ord a => List a -> List a sort xs = sortBy compare xs -- | Sort the elements of a list in increasing order, where elements are @@ -548,7 +546,7 @@ span _ xs = { init: Nil, rest: xs } -- | ``` -- | -- | Running time: `O(n)` -group :: forall a. (Eq a) => List a -> List (List a) +group :: forall a. Eq a => List a -> List (List a) group = groupBy (==) -- | Sort and then group the elements of a list into lists. @@ -556,7 +554,7 @@ group = groupBy (==) -- | ```purescript -- | group' [1,1,2,2,1] == [[1,1,1],[2,2]] -- | ``` -group' :: forall a. (Ord a) => List a -> List (List a) +group' :: forall a. Ord a => List a -> List (List a) group' = group <<< sort -- | Group equal, consecutive elements of a list into lists, using the specified @@ -575,7 +573,7 @@ groupBy eq (Cons x xs) = case span (eq x) xs of -- | Remove duplicate elements from a list. -- | -- | Running time: `O(n^2)` -nub :: forall a. (Eq a) => List a -> List a +nub :: forall a. Eq a => List a -> List a nub = nubBy eq -- | Remove duplicate elements from a list, using the specified @@ -589,7 +587,7 @@ nubBy (==) (Cons x xs) = Cons x (nubBy (==) (filter (\y -> not (x == y)) xs)) -- | Calculate the union of two lists. -- | -- | Running time: `O(n^2)` -union :: forall a. (Eq a) => List a -> List a -> List a +union :: forall a. Eq a => List a -> List a -> List a union = unionBy (==) -- | Calculate the union of two lists, using the specified @@ -602,7 +600,7 @@ unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubBy eq ys) xs -- | Delete the first occurrence of an element from a list. -- | -- | Running time: `O(n)` -delete :: forall a. (Eq a) => a -> List a -> List a +delete :: forall a. Eq a => a -> List a -> List a delete = deleteBy (==) -- | Delete the first occurrence of an element from a list, using the specified @@ -619,13 +617,13 @@ infix 5 difference as \\ -- | Delete the first occurrence of each element in the second list from the first list. -- | -- | Running time: `O(n^2)` -difference :: forall a. (Eq a) => List a -> List a -> List a +difference :: forall a. Eq a => List a -> List a -> List a difference = foldl (flip delete) -- | Calculate the intersection of two lists. -- | -- | Running time: `O(n^2)` -intersect :: forall a. (Eq a) => List a -> List a -> List a +intersect :: forall a. Eq a => List a -> List a -> List a intersect = intersectBy (==) -- | Calculate the intersection of two lists, using the specified @@ -662,7 +660,7 @@ zipWith f xs ys = reverse $ go xs ys Nil -- | A generalization of `zipWith` which accumulates results in some `Applicative` -- | functor. -zipWithA :: forall m a b c. (Applicative m) => (a -> b -> m c) -> List a -> List b -> m (List c) +zipWithA :: forall m a b c. Applicative m => (a -> b -> m c) -> List a -> List b -> m (List c) zipWithA f xs ys = sequence (zipWith f xs ys) -- | Collect pairs of elements at the same positions in two lists. @@ -701,33 +699,19 @@ transpose (Cons (Cons x xs) xss) = -------------------------------------------------------------------------------- -- | Perform a fold using a monadic step function. -foldM :: forall m a b. (Monad m) => (a -> b -> m a) -> a -> List b -> m a -foldM _ a Nil = return a +foldM :: forall m a b. Monad m => (a -> b -> m a) -> a -> List b -> m a +foldM _ a Nil = pure a foldM f a (Cons b bs) = f a b >>= \a' -> foldM f a' bs --------------------------------------------------------------------------------- --- Deprecated functions -------------------------------------------------------- --------------------------------------------------------------------------------- - --- | *Deprecated.* Use `fromFoldable` instead. `toList` will be removed in a --- | later version. -toList :: forall f a. (Foldable f) => f a -> List a -toList = fromFoldable - --- | *Deprecated.* Use `toUnfoldable` instead. `fromList` will be removed in a --- | later version. -fromList :: forall f a. (Unfoldable f) => List a -> f a -fromList = toUnfoldable - -------------------------------------------------------------------------------- -- Instances ------------------------------------------------------------------- -------------------------------------------------------------------------------- -instance showList :: (Show a) => Show (List a) where +instance showList :: Show a => Show (List a) where show Nil = "Nil" - show (Cons x xs) = "Cons (" ++ show x ++ ") (" ++ show xs ++ ")" + show (Cons x xs) = "(Cons " <> show x <> " " <> show xs <> ")" -instance eqList :: (Eq a) => Eq (List a) where +instance eqList :: Eq a => Eq (List a) where eq xs ys = go xs ys true where go _ _ false = false @@ -735,8 +719,7 @@ instance eqList :: (Eq a) => Eq (List a) where go (Cons x xs) (Cons y ys) acc = go xs ys $ acc && (y == x) go _ _ _ = false - -instance ordList :: (Ord a) => Ord (List a) where +instance ordList :: Ord a => Ord (List a) where compare xs ys = go xs ys where go Nil Nil = EQ @@ -760,7 +743,6 @@ instance functorList :: Functor List where go Nil acc = acc go (Cons x xs) acc = go xs $ Cons (f x) acc - instance foldableList :: Foldable List where foldr _ b Nil = b foldr o b (Cons a as) = a `o` foldr o b as @@ -770,7 +752,6 @@ instance foldableList :: Foldable List where go o b (Cons a as) = go o (b `o` a) as foldMap f = foldl (\acc -> append acc <<< f) mempty - instance unfoldableList :: Unfoldable List where unfoldr f b = go b Nil where @@ -804,4 +785,6 @@ instance plusList :: Plus List where instance alternativeList :: Alternative List +instance monadZeroList :: MonadZero List + instance monadPlusList :: MonadPlus List diff --git a/src/Data/List/Lazy.purs b/src/Data/List/Lazy.purs index 4b84d73..e5489b4 100644 --- a/src/Data/List/Lazy.purs +++ b/src/Data/List/Lazy.purs @@ -90,20 +90,19 @@ module Data.List.Lazy , transpose -- , foldM - , toList - , fromList ) where -import Prelude (class Monad, class Bind, class Applicative, class Apply, class Functor, class Semigroup, class Ord, class Eq, class Show, Ordering(EQ, GT, LT), append, flip, ap, (<*>), (<$>), pure, (<>), (<<<), ($), compare, (==), (++), show, otherwise, not, eq, (-), id, (>>=), (+), negate, (>)) +import Prelude import Control.Alt (class Alt) import Control.Alternative (class Alternative) +import Control.Lazy as Z import Control.MonadPlus (class MonadPlus) +import Control.MonadZero (class MonadZero) import Control.Plus (class Plus) -import Control.Lazy as Z import Data.Foldable (class Foldable, foldMap, foldl, foldr, any) -import Data.Lazy (Lazy(), defer, force) +import Data.Lazy (Lazy, defer, force) import Data.Maybe (Maybe(..), isNothing) import Data.Monoid (class Monoid, mempty) import Data.Traversable (class Traversable, traverse, sequence) @@ -121,13 +120,13 @@ runList (List l) = l -- | Convert a list into any unfoldable structure. -- | -- | Running time: `O(n)` -toUnfoldable :: forall f a. (Unfoldable f) => List a -> f a +toUnfoldable :: forall f a. Unfoldable f => List a -> f a toUnfoldable = unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> uncons xs) -- | Construct a list from a foldable structure. -- | -- | Running time: `O(n)` -fromFoldable :: forall f a. (Foldable f) => f a -> List a +fromFoldable :: forall f a. Foldable f => f a -> List a fromFoldable = foldr cons nil -- | A list is either empty (represented by the `Nil` constructor) or non-empty, in @@ -219,7 +218,7 @@ infixr 6 cons as : -- | Insert an element into a sorted list. -- | -- | Running time: `O(n)` -insert :: forall a. (Ord a) => a -> List a -> List a +insert :: forall a. Ord a => a -> List a -> List a insert = insertBy compare -- | Insert an element into a sorted list, using the specified function to determine the ordering @@ -502,7 +501,7 @@ span p xs = -- | ``` -- | -- | Running time: `O(n)` -group :: forall a. (Eq a) => List a -> List (List a) +group :: forall a. Eq a => List a -> List (List a) group = groupBy (==) -- | Group equal, consecutive elements of a list into lists, using the specified @@ -524,7 +523,7 @@ groupBy eq xs = List (go <$> runList xs) -- | Remove duplicate elements from a list. -- | -- | Running time: `O(n^2)` -nub :: forall a. (Eq a) => List a -> List a +nub :: forall a. Eq a => List a -> List a nub = nubBy eq -- | Remove duplicate elements from a list, using the specified @@ -540,7 +539,7 @@ nubBy eq xs = List (go <$> runList xs) -- | Calculate the union of two lists. -- | -- | Running time: `O(n^2)` -union :: forall a. (Eq a) => List a -> List a -> List a +union :: forall a. Eq a => List a -> List a -> List a union = unionBy (==) -- | Calculate the union of two lists, using the specified @@ -553,7 +552,7 @@ unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubBy eq ys) xs -- | Delete the first occurrence of an element from a list. -- | -- | Running time: `O(n)` -delete :: forall a. (Eq a) => a -> List a -> List a +delete :: forall a. Eq a => a -> List a -> List a delete = deleteBy (==) -- | Delete the first occurrence of an element from a list, using the specified @@ -570,14 +569,14 @@ deleteBy eq x xs = List (go <$> runList xs) -- | Delete the first occurrence of each element in the second list from the first list. -- | -- | Running time: `O(n^2)` -difference :: forall a. (Eq a) => List a -> List a -> List a +difference :: forall a. Eq a => List a -> List a -> List a difference = foldl (flip delete) infix 5 difference as \\ -- | Calculate the intersection of two lists. -- | -- | Running time: `O(n^2)` -intersect :: forall a. (Eq a) => List a -> List a -> List a +intersect :: forall a. Eq a => List a -> List a -> List a intersect = intersectBy (==) -- | Calculate the intersection of two lists, using the specified @@ -643,31 +642,17 @@ transpose xs = Just { head: x, tail: xs } -> (x : mapMaybe head xss) : transpose (xs : mapMaybe tail xss) --------------------------------------------------------------------------------- --- Deprecated functions -------------------------------------------------------- --------------------------------------------------------------------------------- - --- | *Deprecated.* Use `fromFoldable` instead. `toList` will be removed in a --- | later version. -toList :: forall f a. (Foldable f) => f a -> List a -toList = fromFoldable - --- | *Deprecated.* Use `toUnfoldable` instead. `fromList` will be removed in a --- | later version. -fromList :: forall f a. (Unfoldable f) => List a -> f a -fromList = toUnfoldable - -------------------------------------------------------------------------------- -- Instances ------------------------------------------------------------------- -------------------------------------------------------------------------------- -instance showList :: (Show a) => Show (List a) where - show xs = "fromStrict (" ++ go (step xs) ++ ")" +instance showList :: Show a => Show (List a) where + show xs = "fromStrict (" <> go (step xs) <> ")" where go Nil = "Nil" - go (Cons x xs) = "Cons (" ++ show x ++ ") (" ++ go (step xs) ++ ")" + go (Cons x xs) = "(Cons " <> show x <> " " <> go (step xs) <> ")" -instance eqList :: (Eq a) => Eq (List a) where +instance eqList :: Eq a => Eq (List a) where eq xs ys = go (step xs) (step ys) where go Nil Nil = true @@ -675,7 +660,7 @@ instance eqList :: (Eq a) => Eq (List a) where | x == y = go (step xs) (step ys) go _ _ = false -instance ordList :: (Ord a) => Ord (List a) where +instance ordList :: Ord a => Ord (List a) where compare xs ys = go (step xs) (step ys) where go Nil Nil = EQ @@ -717,7 +702,7 @@ instance foldableList :: Foldable List where go Nil = b go (Cons a as) = foldl o (b `o` a) as - -- foldMap :: forall a m. (Monoid m) => (a -> m) -> f a -> m + -- foldMap :: forall a m. Monoid m => (a -> m) -> f a -> m foldMap f xs = go (step xs) where go Nil = mempty @@ -732,13 +717,13 @@ instance unfoldableList :: Unfoldable List where go (Just (Tuple a b)) = a : Z.defer \_ -> go (f b) instance traversableList :: Traversable List where - -- traverse :: forall a b m. (Applicative m) => (a -> m b) -> t a -> m (t b) + -- traverse :: forall a b m. Applicative m => (a -> m b) -> t a -> m (t b) traverse f xs = go (step xs) where go Nil = pure nil go (Cons x xs) = cons <$> f x <*> traverse f xs - -- sequence :: forall a m. (Applicative m) => t (m a) -> m (t a) + -- sequence :: forall a m. Applicative m => t (m a) -> m (t a) sequence xs = go (step xs) where go Nil = pure nil @@ -763,4 +748,6 @@ instance plusList :: Plus List where instance alternativeList :: Alternative List +instance monadZeroList :: MonadZero List + instance monadPlusList :: MonadPlus List diff --git a/src/Data/List/Partial.purs b/src/Data/List/Partial.purs new file mode 100644 index 0000000..8a063ba --- /dev/null +++ b/src/Data/List/Partial.purs @@ -0,0 +1,30 @@ +-- | Partial helper functions for working with strict linked lists. +module Data.List.Partial where + +import Data.List (List(..)) + +-- | Get the first element of a non-empty list. +-- | +-- | Running time: `O(1)`. +head :: forall a. Partial => List a -> a +head (Cons x _) = x + +-- | Get all but the first element of a non-empty list. +-- | +-- | Running time: `O(1)` +tail :: forall a. Partial => List a -> List a +tail (Cons _ xs) = xs + +-- | Get the last element of a non-empty list. +-- | +-- | Running time: `O(n)` +last :: forall a. Partial => List a -> a +last (Cons x Nil) = x +last (Cons _ xs) = last xs + +-- | Get all but the last element of a non-empty list. +-- | +-- | Running time: `O(n)` +init :: forall a. Partial => List a -> List a +init (Cons x Nil) = Nil +init (Cons x xs) = Cons x (init xs) diff --git a/src/Data/List/Unsafe.js b/src/Data/List/Unsafe.js deleted file mode 100644 index cd71fc9..0000000 --- a/src/Data/List/Unsafe.js +++ /dev/null @@ -1,8 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.List.Unsafe - -exports.unsafeThrow = function (msg) { - throw new Error(msg); -}; diff --git a/src/Data/List/Unsafe.purs b/src/Data/List/Unsafe.purs deleted file mode 100644 index 533127c..0000000 --- a/src/Data/List/Unsafe.purs +++ /dev/null @@ -1,45 +0,0 @@ --- | Unsafe helper functions for working with strict linked lists. --- | --- | _Note_: these functions should be used with care, and may result in unspecified --- | behavior, including runtime exceptions. - -module Data.List.Unsafe - ( head - , tail - , last - , init - ) where - -import Data.List (List(..)) - --- | Get the first element of a non-empty list. --- | --- | Running time: `O(1)`. -head :: forall a. List a -> a -head (Cons x _) = x -head Nil = unsafeThrow "Data.List.Unsafe.head called on empty list" - --- | Get all but the first element of a non-empty list. --- | --- | Running time: `O(1)` -tail :: forall a. List a -> List a -tail (Cons _ xs) = xs -tail Nil = unsafeThrow "Data.List.Unsafe.tail called on empty list" - --- | Get the last element of a non-empty list. --- | --- | Running time: `O(n)` -last :: forall a. List a -> a -last (Cons x Nil) = x -last (Cons _ xs) = last xs -last Nil = unsafeThrow "Data.List.Unsafe.last called on empty list" - --- | Get all but the last element of a non-empty list. --- | --- | Running time: `O(n)` -init :: forall a. List a -> List a -init (Cons x Nil) = Nil -init (Cons x xs) = Cons x (init xs) -init Nil = unsafeThrow "Data.List.Unsafe.init called on empty list" - -foreign import unsafeThrow :: forall a. String -> a diff --git a/src/Data/List/ZipList.purs b/src/Data/List/ZipList.purs index f8a44d4..b568d39 100644 --- a/src/Data/List/ZipList.purs +++ b/src/Data/List/ZipList.purs @@ -6,14 +6,14 @@ module Data.List.ZipList , runZipList ) where -import Prelude (class Applicative, class Apply, class Functor, class Semigroup, class Ord, class Eq, class Show, append, (<<<), ($), map, (<$>), (++), compare, eq, show) +import Prelude import Control.Alt (class Alt) import Control.Alternative (class Alternative) import Control.Plus (class Plus) import Data.Foldable (class Foldable, foldMap, foldl, foldr) -import Data.List.Lazy (List(), repeat, zipWith) +import Data.List.Lazy (List, repeat, zipWith) import Data.Monoid (class Monoid, mempty) import Data.Traversable (class Traversable, traverse, sequence) @@ -25,17 +25,17 @@ newtype ZipList a = ZipList (List a) runZipList :: forall a. ZipList a -> List a runZipList (ZipList xs) = xs -instance showZipList :: (Show a) => Show (ZipList a) where - show (ZipList xs) = "(ZipList " ++ show xs ++ ")" +instance showZipList :: Show a => Show (ZipList a) where + show (ZipList xs) = "(ZipList " <> show xs <> ")" -instance eqZipList :: (Eq a) => Eq (ZipList a) where +instance eqZipList :: Eq a => Eq (ZipList a) where eq z1 z2 = runZipList z1 `eq` runZipList z2 -instance ordZipList :: (Ord a) => Ord (ZipList a) where +instance ordZipList :: Ord a => Ord (ZipList a) where compare z1 z2 = runZipList z1 `compare` runZipList z2 instance semigroupZipList :: Semigroup (ZipList a) where - append z1 z2 = ZipList (runZipList z1 ++ runZipList z2) + append z1 z2 = ZipList (runZipList z1 <> runZipList z2) instance monoidZipList :: Monoid (ZipList a) where mempty = ZipList mempty diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index 10da0cf..1ccfa02 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -1,15 +1,19 @@ module Test.Data.List (testList) where -import Prelude (Unit, (*), zero, (/=), mod, (+), (==), ($), bind, pure, void, show, (<), (&&), compare, flip, const, (<<<), map, negate) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Console (CONSOLE(), log) +import Prelude + +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + import Data.Foldable (foldMap, foldl) +import Data.List (List(Nil, Cons), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, init, tail, last, head, insertBy, insert, snoc, null, replicateM, replicate, singleton, fromFoldable, transpose, mapWithIndex, (:)) +import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Monoid.Additive (Additive(Additive)) -import Data.List (List(Nil, Cons), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, init, tail, last, head, insertBy, insert, snoc, null, replicateM, replicate, singleton, fromFoldable, transpose, (:)) -import Data.Maybe (Maybe(..), isNothing) -import Data.Maybe.Unsafe (fromJust) import Data.Tuple (Tuple(..)) -import Test.Assert (ASSERT(), assert) + +import Partial.Unsafe (unsafePartial) + +import Test.Assert (ASSERT, assert) testList :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit testList = do @@ -96,11 +100,11 @@ testList = do log "uncons should split an list into a head and tail record when there is at least one item" let u1 = uncons (l [1]) - assert $ (fromJust u1).head == 1 - assert $ (fromJust u1).tail == l [] + assert $ unsafePartial (fromJust u1).head == 1 + assert $ unsafePartial (fromJust u1).tail == l [] let u2 = uncons (l [1, 2, 3]) - assert $ (fromJust u2).head == 1 - assert $ (fromJust u2).tail == l [2, 3] + assert $ unsafePartial (fromJust u2).head == 1 + assert $ unsafePartial (fromJust u2).tail == l [2, 3] log "(!!) should return Just x when the index is within the bounds of the list" assert $ l [1, 2, 3] !! 0 == (Just 1) @@ -193,7 +197,7 @@ testList = do assert $ catMaybes (l [Nothing, Just 2, Nothing, Just 4]) == l [2, 4] log "mapWithIndex should take a list of values and apply a function which also takes the index into account" - assert $ mapWithIndex (\x ix -> x + ix) (toList [0, 1, 2, 3]) == toList [0, 2, 4, 6] + assert $ mapWithIndex (\x ix -> x + ix) (fromFoldable [0, 1, 2, 3]) == fromFoldable [0, 2, 4, 6] log "sort should reorder a list into ascending order based on the result of compare" assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6] diff --git a/test/Test/Data/List/Lazy.purs b/test/Test/Data/List/Lazy.purs index 28f055f..2702fe5 100644 --- a/test/Test/Data/List/Lazy.purs +++ b/test/Test/Data/List/Lazy.purs @@ -1,13 +1,17 @@ module Test.Data.List.Lazy (testListLazy) where -import Prelude (Unit, (*), zero, (/=), mod, (==), ($), bind, show, (<), (&&), map, const, (+), (<<<), negate, compare, flip) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Console (CONSOLE(), log) +import Prelude + +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + import Data.List.Lazy (List, nil, cons, zip, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group, span, dropWhile, drop, takeWhile, take, catMaybes, mapMaybe, range, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, (!!), uncons, init, tail, last, head, insertBy, insert, length, null, singleton, fromFoldable, transpose, (:)) -import Data.Maybe (Maybe(..), isNothing) -import Data.Maybe.Unsafe (fromJust) +import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Tuple (Tuple(..)) -import Test.Assert (ASSERT(), assert) + +import Partial.Unsafe (unsafePartial) + +import Test.Assert (ASSERT, assert) testListLazy :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit testListLazy = do @@ -91,11 +95,11 @@ testListLazy = do log "uncons should split an list into a head and tail record when there is at least one item" let u1 = uncons (l [1]) - assert $ (fromJust u1).head == 1 - assert $ (fromJust u1).tail == l [] + assert $ unsafePartial (fromJust u1).head == 1 + assert $ unsafePartial(fromJust u1).tail == l [] let u2 = uncons (l [1, 2, 3]) - assert $ (fromJust u2).head == 1 - assert $ (fromJust u2).tail == l [2, 3] + assert $ unsafePartial (fromJust u2).head == 1 + assert $ unsafePartial (fromJust u2).tail == l [2, 3] log "(!!) should return Just x when the index is within the bounds of the list" assert $ l [1, 2, 3] !! 0 == (Just 1) diff --git a/test/Test/Data/List/Partial.purs b/test/Test/Data/List/Partial.purs new file mode 100644 index 0000000..9780577 --- /dev/null +++ b/test/Test/Data/List/Partial.purs @@ -0,0 +1,41 @@ +module Test.Data.List.Partial (testListPartial) where + +import Prelude + +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +import Data.List (List(..), fromFoldable) +import Data.List.Partial (init, tail, last, head) + +import Partial.Unsafe (unsafePartial) + +import Test.Assert (ASSERT, assert, assertThrows) + +testListPartial :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit +testListPartial = do + let l = fromFoldable + + log "head should return a Just-wrapped first value of a non-empty list" + assert $ unsafePartial $ head (l ["foo", "bar"]) == "foo" + + log "head should throw an error for an empty list" + assertThrows \_ -> unsafePartial $ head Nil + + log "last should return a Just-wrapped last value of a non-empty list" + assert $ unsafePartial $ last (l ["foo", "bar"]) == "bar" + + log "last should throw an error for an empty list" + assertThrows \_ -> unsafePartial $ last Nil + + log "tail should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" + assert $ unsafePartial $ tail (l ["foo", "bar", "baz"]) == l ["bar", "baz"] + + log "tail should throw an error for an empty list" + assertThrows \_ -> unsafePartial $ tail Nil + + log "init should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" + assert $ unsafePartial $ init (l ["foo", "bar", "baz"]) == l ["foo", "bar"] + + log "init should throw an error for an empty list" + assertThrows \_ -> unsafePartial $ init Nil diff --git a/test/Test/Data/List/Unsafe.purs b/test/Test/Data/List/Unsafe.purs deleted file mode 100644 index 261297d..0000000 --- a/test/Test/Data/List/Unsafe.purs +++ /dev/null @@ -1,36 +0,0 @@ -module Test.Data.List.Unsafe (testListUnsafe) where - -import Prelude (Unit, bind, (==), ($)) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Console (CONSOLE(), log) -import Data.List (List(..), fromFoldable) -import Data.List.Unsafe (init, tail, last, head) -import Test.Assert (ASSERT(), assert, assertThrows) - -testListUnsafe :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit -testListUnsafe = do - let l = fromFoldable - - log "head should return a Just-wrapped first value of a non-empty list" - assert $ head (l ["foo", "bar"]) == "foo" - - log "head should throw an error for an empty list" - assertThrows \_ -> head Nil - - log "last should return a Just-wrapped last value of a non-empty list" - assert $ last (l ["foo", "bar"]) == "bar" - - log "last should throw an error for an empty list" - assertThrows \_ -> last Nil - - log "tail should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ tail (l ["foo", "bar", "baz"]) == l ["bar", "baz"] - - log "tail should throw an error for an empty list" - assertThrows \_ -> tail Nil - - log "init should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ init (l ["foo", "bar", "baz"]) == l ["foo", "bar"] - - log "init should throw an error for an empty list" - assertThrows \_ -> init Nil diff --git a/test/Test/Data/List/ZipList.purs b/test/Test/Data/List/ZipList.purs index 48b387b..1c1a6f1 100644 --- a/test/Test/Data/List/ZipList.purs +++ b/test/Test/Data/List/ZipList.purs @@ -1,12 +1,15 @@ module Test.Data.List.ZipList (testZipList) where -import Prelude (class Eq, Unit, (<<<), (<*>), (<$>), (==), ($), const, (*), bind, (+)) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Console (CONSOLE(), log) +import Prelude + +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +import Data.Array as Array import Data.List.Lazy as LazyList import Data.List.ZipList (ZipList(..)) -import Data.Array as Array -import Test.Assert (ASSERT(), assert) + +import Test.Assert (ASSERT, assert) testZipList :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit testZipList = do @@ -15,7 +18,7 @@ testZipList = do testZipWith (*) [1,2,3] [4,5,6] testZipWith const [1,2,3] [4,5,6] -testZipWith :: forall a b c eff. (Eq c) => (a -> b -> c) -> Array a -> Array b -> Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit +testZipWith :: forall a b c eff. Eq c => (a -> b -> c) -> Array a -> Array b -> Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit testZipWith f xs ys = assert $ (f <$> l xs <*> l ys) == l (Array.zipWith f xs ys) diff --git a/test/Test/Main.purs b/test/Test/Main.purs index fef0e3d..17c930c 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -1,17 +1,19 @@ module Test.Main where -import Prelude (Unit, bind) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Console (CONSOLE()) -import Test.Assert (ASSERT()) +import Prelude + +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE) + +import Test.Assert (ASSERT) import Test.Data.List (testList) import Test.Data.List.Lazy (testListLazy) +import Test.Data.List.Partial (testListPartial) import Test.Data.List.ZipList (testZipList) -import Test.Data.List.Unsafe (testListUnsafe) main :: forall eff. Eff (assert :: ASSERT, console :: CONSOLE | eff) Unit main = do testList testListLazy testZipList - testListUnsafe + testListPartial