diff --git a/LICENSE b/LICENSE index 58b0299..311379c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,20 +1,26 @@ -The MIT License (MIT) +Copyright 2018 PureScript -Copyright (c) 2014 PureScript +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bower.json b/bower.json index 8222ab7..a50b3bf 100644 --- a/bower.json +++ b/bower.json @@ -1,8 +1,7 @@ { "name": "purescript-unfoldable", "homepage": "https://github.com/purescript/purescript-unfoldable", - "description": "Unfoldable Functors", - "license": "MIT", + "license": "BSD-3-Clause", "repository": { "type": "git", "url": "git://github.com/purescript/purescript-unfoldable.git" @@ -17,11 +16,14 @@ "package.json" ], "dependencies": { - "purescript-partial": "^1.2.0", - "purescript-tuples": "^4.0.0" + "purescript-foldable-traversable": "^4.0.0", + "purescript-maybe": "^4.0.0", + "purescript-partial": "^2.0.0", + "purescript-prelude": "^4.0.0", + "purescript-tuples": "^5.0.0" }, "devDependencies": { - "purescript-assert": "^3.0.0", - "purescript-console": "^3.0.0" + "purescript-assert": "^4.0.0", + "purescript-console": "^4.0.0" } } diff --git a/package.json b/package.json index 132cefc..6615039 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,9 @@ "test": "pulp test" }, "devDependencies": { - "eslint": "^3.17.1", - "pulp": "^10.0.4", - "purescript-psa": "^0.5.0-rc.1", - "rimraf": "^2.6.1" + "eslint": "^4.19.1", + "pulp": "^12.2.0", + "purescript-psa": "^0.6.0", + "rimraf": "^2.6.2" } } diff --git a/src/Data/Unfoldable.purs b/src/Data/Unfoldable.purs index 3ed0ad0..e4d193e 100644 --- a/src/Data/Unfoldable.purs +++ b/src/Data/Unfoldable.purs @@ -9,9 +9,8 @@ module Data.Unfoldable , replicate , replicateA , none - , singleton - , range , fromMaybe + , module Data.Unfoldable1 ) where import Prelude @@ -19,7 +18,7 @@ import Prelude import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Traversable (class Traversable, sequence) import Data.Tuple (Tuple(..), fst, snd) - +import Data.Unfoldable1 (class Unfoldable1, unfoldr1, singleton, range, replicate1, replicate1A) import Partial.Unsafe (unsafePartial) -- | This class identifies data structures which can be _unfolded_. @@ -29,7 +28,7 @@ import Partial.Unsafe (unsafePartial) -- | - If `f b` is `Nothing`, then `unfoldr f b` should be empty. -- | - If `f b` is `Just (Tuple a b1)`, then `unfoldr f b` should consist of `a` -- | appended to the result of `unfoldr f b1`. -class Unfoldable t where +class Unfoldable1 t <= Unfoldable t where unfoldr :: forall a b. (b -> Maybe (Tuple a b)) -> b -> t a instance unfoldableArray :: Unfoldable Array where @@ -48,9 +47,9 @@ foreign import unfoldrArrayImpl -- | Replicate a value some natural number of times. -- | For example: -- | --- | ~~~ purescript +-- | ``` purescript -- | replicate 2 "foo" == ["foo", "foo"] :: Array String --- | ~~~ +-- | ``` replicate :: forall f a. Unfoldable f => Int -> a -> f a replicate n v = unfoldr step n where @@ -73,26 +72,12 @@ replicateA n m = sequence (replicate n m) -- | The container with no elements - unfolded with zero iterations. -- | For example: -- | --- | ~~~ purescript +-- | ``` purescript -- | none == [] :: forall a. Array a --- | ~~~ +-- | ``` none :: forall f a. Unfoldable f => f a none = unfoldr (const Nothing) unit --- | Contain a single value. --- | For example: --- | --- | ~~~ purescript --- | singleton "foo" == ["foo"] :: Array String --- | ~~~ -singleton :: forall f a. Unfoldable f => a -> f a -singleton = replicate 1 - --- | Create an Unfoldable containing a range of values, with both endpoints. -range :: forall f. Unfoldable f => Int -> Int -> f Int -range start end = - unfoldr (\i -> if i <= end then Just (Tuple i $ i + 1) else Nothing) start - -- | Convert a Maybe to any Unfoldable like lists and arrays. fromMaybe :: forall f a. Unfoldable f => Maybe a -> f a fromMaybe = unfoldr (\b -> flip Tuple Nothing <$> b) diff --git a/src/Data/Unfoldable1.js b/src/Data/Unfoldable1.js new file mode 100644 index 0000000..d794fdf --- /dev/null +++ b/src/Data/Unfoldable1.js @@ -0,0 +1,23 @@ +"use strict"; + +exports.unfoldr1ArrayImpl = function (isNothing) { + return function (fromJust) { + return function (fst) { + return function (snd) { + return function (f) { + return function (b) { + var result = []; + var value = b; + while (true) { // eslint-disable-line no-constant-condition + var tuple = f(value); + result.push(fst(tuple)); + var maybe = snd(tuple); + if (isNothing(maybe)) return result; + value = fromJust(maybe); + } + }; + }; + }; + }; + }; +}; diff --git a/src/Data/Unfoldable1.purs b/src/Data/Unfoldable1.purs index c8f51e5..a2f0314 100644 --- a/src/Data/Unfoldable1.purs +++ b/src/Data/Unfoldable1.purs @@ -8,9 +8,10 @@ module Data.Unfoldable1 import Prelude -import Data.Maybe (Maybe(..)) +import Data.Maybe (Maybe(..), fromJust, isNothing) import Data.Semigroup.Traversable (class Traversable1, sequence1) -import Data.Tuple (Tuple(..)) +import Data.Tuple (Tuple(..), fst, snd) +import Partial.Unsafe (unsafePartial) -- | This class identifies non-empty data structures which can be _unfolded_. -- | @@ -20,6 +21,19 @@ import Data.Tuple (Tuple(..)) class Unfoldable1 t where unfoldr1 :: forall a b. (b -> Tuple a (Maybe b)) -> b -> t a +instance unfoldable1Array :: Unfoldable1 Array where + unfoldr1 = unfoldr1ArrayImpl isNothing (unsafePartial fromJust) fst snd + +foreign import unfoldr1ArrayImpl + :: forall a b + . (forall x. Maybe x -> Boolean) + -> (forall x. Maybe x -> x) + -> (forall x y. Tuple x y -> x) + -> (forall x y. Tuple x y -> y) + -> (b -> Tuple a (Maybe b)) + -> b + -> Array a + -- | Replicate a value `n` times. At least one value will be produced, so values -- | `n < 1` less than one will be ignored. -- | diff --git a/test/Main.purs b/test/Main.purs index ae769e8..6ebef5b 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,17 +2,18 @@ module Test.Main where import Prelude -import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (CONSOLE, log, logShow) +import Data.Eq (class Eq1) import Data.Maybe (Maybe(..)) import Data.Tuple (Tuple(..), uncurry) import Data.Unfoldable as U import Data.Unfoldable1 as U1 -import Test.Assert (ASSERT, assert) +import Effect (Effect) +import Effect.Console (log, logShow) +import Test.Assert (assert) data NonEmpty f a = NonEmpty a (f a) -derive instance eqNonEmpty :: (Eq (f a), Eq a) => Eq (NonEmpty f a) +derive instance eqNonEmpty :: (Eq1 f, Eq a) => Eq (NonEmpty f a) instance unfoldable1NonEmpty :: U.Unfoldable f => U1.Unfoldable1 (NonEmpty f) where unfoldr1 f = uncurry NonEmpty <<< map (U.unfoldr $ map f) <<< f @@ -28,7 +29,7 @@ collatz = U.unfoldr step then n / 2 else n * 3 + 1 -main :: Eff (assert :: ASSERT, console :: CONSOLE) Unit +main :: Effect Unit main = do log "Collatz 1000" logShow $ collatz 1000 @@ -52,12 +53,10 @@ main = do [2,1,1],[2,1,2], [2,2,1],[2,2,2] ] - log "Test U.range" - assert $ U.range 1 0 == [] - assert $ U.range 0 0 == [0] - assert $ U.range 0 2 == [0, 1, 2] - - log "Test U1.range" + log "Test range" + assert $ U1.range 1 0 == [1, 0] + assert $ U1.range 0 0 == [0] + assert $ U1.range 0 2 == [0, 1, 2] assert $ U1.range 1 0 == NonEmpty 1 [0] assert $ U1.range 0 0 == NonEmpty 0 [] assert $ U1.range 0 2 == NonEmpty 0 [1, 2]