Skip to content

Deduplicate testing code - with records #200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Notable changes to this project are documented in this file. The format is based
## [Unreleased]

Breaking changes:
- Rename `scanrLazy` to `scanlLazy` and fix parameter ordering (#161)
- Rename `group'` to `groupAll` (#182)
- Change `Alt ZipList` to satisfy distributivity (#150)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to implement this PR without the above breaking changes? The changes could still be made in a separate PR that we could wait to merge until another breaking PS release is made.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes have already been made and released; I think this is just a bad merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm planning on merging this after #191 goes though, so I incorporated changes from that PR here too.
But yes, this is a pretty sloppy PR. Just wanted to upload the WIP to share some context during yesterday's meetup.

New features:

Expand Down
46 changes: 37 additions & 9 deletions src/Data/List.purs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module Data.List
, someRec
, many
, manyRec
-- , replicate -- questionable specialization

, null
, length
Expand Down Expand Up @@ -95,6 +96,13 @@ module Data.List
, foldM

, module Exports

-- additions
, appendFoldable

, cons'
, snoc'

) where

import Prelude
Expand All @@ -109,7 +117,7 @@ import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, f
import Data.FunctorWithIndex (mapWithIndex) as FWI
import Data.List.Internal (emptySet, insertAndLookupBy)
import Data.List.Types (List(..), (:))
import Data.List.Types (NonEmptyList(..)) as NEL
import Data.List.Types as NEL
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.NonEmpty ((:|))
Expand All @@ -119,6 +127,18 @@ import Data.Tuple (Tuple(..))
import Data.Unfoldable (class Unfoldable, unfoldr)
import Prim.TypeError (class Warn, Text)


---------- Additions

appendFoldable :: forall t a. Foldable t => List a -> t a -> List a
appendFoldable xs ys = xs <> fromFoldable ys

cons' :: forall a. a -> NEL.NonEmptyList a -> List a
cons' x xs = Cons x $ NEL.toList xs

snoc' :: forall a. NEL.NonEmptyList a -> a -> List a
snoc' xs x = snoc (NEL.toList xs) x

-- | Convert a list into any unfoldable structure.
-- |
-- | Running time: `O(n)`
Expand Down Expand Up @@ -180,6 +200,15 @@ manyRec p = tailRecM go Nil
aa <- (Loop <$> p) <|> pure (Done unit)
pure $ bimap (_ : acc) (\_ -> reverse acc) aa

-- Questionable whether this should be specialized
-- -- | Create a list containing a value repeated n times
-- replicate :: forall a. Int -> a -> List a
-- replicate num x = go num Nil
-- where
-- go n xs | n < 1 = xs
-- | otherwise = go (n - 1) (x : xs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether this should be added. Does anyone use this? Would anyone use this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering the same. Current plan is to just provide a specialized replicate for List.Lazy, and otherwise use Unfoldable's replicate here. So I'd remove this commented block during clean-up.
The full API proposal can be found in #183 (comment). Some related questions about what to include or not can be found at the end of that comment.



--------------------------------------------------------------------------------
-- List size -------------------------------------------------------------------
--------------------------------------------------------------------------------
Expand Down Expand Up @@ -626,17 +655,16 @@ groupBy _ Nil = Nil
groupBy eq (x : xs) = case span (eq x) xs of
{ init: ys, rest: zs } -> NEL.NonEmptyList (x :| ys) : groupBy eq zs

-- | Group equal elements of a list into lists, using the specified
-- | equivalence relation to determine equality.
-- |
-- | For example,
-- | Sort, then group equal elements of a list into lists, using the provided comparison function.
-- |
-- | ```purescript
-- | groupAllBy (\a b -> odd a && odd b) (1 : 3 : 2 : 4 : 3 : 3 : Nil) ==
-- | (NonEmptyList (NonEmpty 1 Nil)) : (NonEmptyList (NonEmpty 2 Nil)) : (NonEmptyList (NonEmpty 3 (3 : 3 : Nil))) : (NonEmptyList (NonEmpty 4 Nil)) : Nil
-- | groupAllBy (compare `on` (_ `div` 10)) (32 : 31 : 21 : 22 : 11 : 33 : Nil) ==
-- | NonEmptyList (11 :| Nil) : NonEmptyList (21 :| 22 : Nil) : NonEmptyList (32 :| 31 : 33) : Nil
-- | ```
groupAllBy :: forall a. Ord a => (a -> a -> Boolean) -> List a -> List (NEL.NonEmptyList a)
groupAllBy p = groupBy p <<< sort
-- |
-- | Running time: `O(n log n)`
groupAllBy :: forall a. (a -> a -> Ordering) -> List a -> List (NEL.NonEmptyList a)
groupAllBy p = groupBy (\x y -> p x y == EQ) <<< sortBy p

-- | Returns a lists of elements which do and do not satisfy a predicate.
-- |
Expand Down
65 changes: 64 additions & 1 deletion src/Data/List/Lazy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ module Data.List.Lazy
, stripPrefix
, slice
, take
, takeEnd
, takeWhile
, drop
, dropWhile
, span
, group
-- , group'
, groupAll
, groupBy
, partition

Expand Down Expand Up @@ -94,6 +96,22 @@ module Data.List.Lazy
, scanlLazy

, module Exports

-- additions
, appendFoldable
, someRec
, sort
, sortBy

, cons'
, dropEnd
, groupAllBy
, snoc'
, manyRec

, replicate1
, replicate1M

) where

import Prelude
Expand All @@ -102,6 +120,7 @@ import Control.Alt ((<|>))
import Control.Alternative (class Alternative)
import Control.Lazy as Z
import Control.Monad.Rec.Class as Rec
import Control.Monad.Rec.Class (class MonadRec)
import Data.Foldable (class Foldable, foldr, any, foldl)
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
import Data.Lazy (defer)
Expand All @@ -115,6 +134,36 @@ import Data.Traversable (scanl, scanr) as Exports
import Data.Traversable (sequence)
import Data.Tuple (Tuple(..))
import Data.Unfoldable (class Unfoldable, unfoldr)
import Partial.Unsafe (unsafeCrashWith)

-- Additions
appendFoldable :: forall t a. Foldable t => List a -> t a -> List a
appendFoldable _ _ = unsafeCrashWith "todo appendFoldable for Lazy List"
someRec :: forall f a. MonadRec f => Alternative f => f a -> f (List a)
someRec _ = unsafeCrashWith "todo someRec for Lazy List"
sort :: forall a. Ord a => List a -> List a
sort _ = unsafeCrashWith "todo sort for Lazy List"
sortBy :: forall a. (a -> a -> Ordering) -> List a -> List a
sortBy _ _ = unsafeCrashWith "todo sortBy for Lazy List"

cons' :: forall a. a -> NEL.NonEmptyList a -> List a
cons' _ _ = unsafeCrashWith "todo cons' for Lazy List"
dropEnd :: forall a. Int -> List a -> List a
dropEnd _ _ = unsafeCrashWith "todo dropEnd for Lazy List"
groupAllBy :: forall a. (a -> a -> Ordering) -> List a -> List (NEL.NonEmptyList a)
groupAllBy _ _ = unsafeCrashWith "todo groupAllBy for Lazy List"
snoc' :: forall a. NEL.NonEmptyList a -> a -> List a
snoc' _ _ = unsafeCrashWith "todo snoc' for Lazy List"

manyRec :: forall f a. MonadRec f => Alternative f => f a -> f (List a)
manyRec _ = unsafeCrashWith "todo manyRec for Lazy List"

-- Specialized from Unfoldable1's replicate1 / replicate1A
replicate1 :: forall a. Int -> a -> List a
replicate1 _ _ = unsafeCrashWith "todo replicate1 for Lazy List"

replicate1M :: forall m a. Monad m => Int -> m a -> m (List a)
replicate1M _ _ = unsafeCrashWith "todo replicate1M for Lazy List"

-- | Convert a list into any unfoldable structure.
-- |
Expand Down Expand Up @@ -506,6 +555,12 @@ take n = if n <= 0
go _ Nil = Nil
go n' (Cons x xs) = Cons x (take (n' - 1) xs)

-- | Take the specified number of elements from the end of a list.
-- |
-- | Running time: Todo
takeEnd :: forall a. Int -> List a -> List a
takeEnd _ _ = unsafeCrashWith "todo takeEnd for Lazy List"

-- | Take those elements from the front of a list which match a predicate.
-- |
-- | Running time (worst case): `O(n)`
Expand All @@ -521,7 +576,7 @@ takeWhile p = List <<< map go <<< unwrap
drop :: forall a. Int -> List a -> List a
drop n = List <<< map (go n) <<< unwrap
where
go 0 xs = xs
go n' xs | n' < 1 = xs
go _ Nil = Nil
go n' (Cons _ xs) = go (n' - 1) (step xs)

Expand Down Expand Up @@ -566,6 +621,14 @@ span p xs =
group :: forall a. Eq a => List a -> List (NEL.NonEmptyList a)
group = groupBy (==)

-- | Group equal elements of a list into lists.
-- |
-- | Todo - fix documentation mismatch of above `group` with non-lazy version.
-- | ```
groupAll :: forall a. Ord a => List a -> List (NEL.NonEmptyList a)
groupAll = unsafeCrashWith "todo groupAll for Lazy List"
--groupAll = group <<< sort

-- | Group equal, consecutive elements of a list into lists, using the specified
-- | equivalence relation to determine equality.
-- |
Expand Down
Loading