packages feed

dlist-nonempty (empty) → 0.1

raw patch · 10 files changed

+664/−0 lines, 10 filesdep +Cabaldep +QuickCheckdep +basesetup-changed

Dependencies added: Cabal, QuickCheck, base, base-compat, criterion, deepseq, dlist, dlist-instances, dlist-nonempty, quickcheck-instances, semigroupoids, semigroups

Files

+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2006-2009 Don Stewart, 2013-2016 Sean Leather, 2017 Oleg Grenrus++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * 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.++    * Neither the name of Don Stewart nor the names of other+      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+OWNER 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.
+ README.md view
@@ -0,0 +1,33 @@+# Difference Lists in Haskell++The `NonEmpty` version of difference lists: list-like type supporting O(1) append ans snoc operations.++This is a fork of a [`dlist`](http://hackage.haskell.org/package/dlist) package.++```+benchmarking append 1000/List+time                 27.66 ms   (27.30 ms .. 28.01 ms)+                     0.999 R²   (0.999 R² .. 1.000 R²)+mean                 28.39 ms   (28.21 ms .. 28.58 ms)+std dev              391.5 μs   (311.7 μs .. 510.3 μs)++benchmarking append 1000/NonEmpty+time                 33.67 ms   (33.01 ms .. 34.27 ms)+                     0.999 R²   (0.999 R² .. 1.000 R²)+mean                 34.07 ms   (33.90 ms .. 34.29 ms)+std dev              419.3 μs   (308.9 μs .. 549.3 μs)++benchmarking append 1000/DList+time                 57.46 μs   (56.95 μs .. 58.12 μs)+                     0.999 R²   (0.998 R² .. 0.999 R²)+mean                 57.98 μs   (57.61 μs .. 58.41 μs)+std dev              1.398 μs   (1.115 μs .. 1.871 μs)+variance introduced by outliers: 22% (moderately inflated)++benchmarking append 1000/NonEmptyDList+time                 90.37 μs   (89.09 μs .. 91.44 μs)+                     0.999 R²   (0.998 R² .. 0.999 R²)+mean                 89.31 μs   (88.61 μs .. 89.96 μs)+std dev              2.244 μs   (1.763 μs .. 2.988 μs)+variance introduced by outliers: 22% (moderately inflated)+```
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ bench/Main.hs view
@@ -0,0 +1,29 @@+import Criterion.Main++import Prelude ()+import Prelude.Compat++import Data.List (foldl')+import Data.Foldable (toList)+import Data.Semigroup (Semigroup (..))+import Data.DList.Instances ()++import qualified Data.List.NonEmpty as NE+import qualified Data.DList as DList+import qualified Data.DList.NonEmpty as NEDList++sum' :: (Semigroup (f Int), Foldable f) => Int -> f Int -> Int+sum' m x = foldl' (+) 0 $ toList $ go x m+  where+    go y n | n <= 0    = y+           | otherwise = go (y <> x) (n - 1)++main :: IO ()+main = defaultMain+    [ bgroup "append 1000"+        [ bench "List"          $ whnf (sum' 1000) $ [1,2,3,4,5]+        , bench "NonEmpty"      $ whnf (sum' 1000) $ 1 NE.:| [2,3,4,5]+        , bench "DList"         $ whnf (sum' 1000) $ DList.fromList [1,2,3,4,5]+        , bench "NonEmptyDList" $ whnf (sum' 1000) $ NEDList.fromNonEmpty $ 1 NE.:| [2,3,4,5]+        ]+    ]
+ dlist-nonempty.cabal view
@@ -0,0 +1,84 @@+name:                   dlist-nonempty+version:                0.1+synopsis:               Non-empty difference lists+description:+  Difference lists are a list-like type supporting O(1) append. This is+  particularly useful for efficient logging and pretty printing (e.g. with the+  Writer monad), where list append quickly becomes too expensive.+  .+  > DList a         ≅ [a] -> [a]+  > NonEmptyDList a ≅ [a] -> NonEmpty a+  .+  For empty variant, @DList@, see <http://hackage.haskell.org/package/dlist dlist package>.+category:               Data+license:                BSD3+license-file:           LICENSE+author:                 Don Stewart, Oleg  Grenrus+maintainer:             Oleg Grenrus <oleg.grenrus@iki.fi>+copyright:              2006-2009 Don Stewart, 2013-2016 Sean Leather, 2017 Oleg Grenrus+homepage:               https://github.com/phadej/dlist-nonempty+bug-reports:            https://github.com/phadej/dlist-nonempty/issues+extra-source-files:     README.md+build-type:             Simple+cabal-version:          >=1.10+tested-with:+  GHC==7.4.2,+  GHC==7.6.3,+  GHC==7.8.4,+  GHC==7.10.3,+  GHC==8.0.2,+  GHC==8.2.1++source-repository head+  type:                 git+  location:             git://github.com/phadej/dlist-nonempty.git++library+  default-language:     Haskell2010+  hs-source-dirs:       src+  build-depends:+                        base          >=4.5   && <4.11,+                        base-compat   >=0.9.1 && <0.10,+                        deepseq       >=1.1   && <2,+                        dlist         >=0.8   && <0.9,+                        semigroupoids >=5.1   && <5.3+  if !impl(ghc >= 8.0)+    build-depends:+                        semigroups >=0.18.2 && <0.19+  other-extensions:     CPP+  exposed-modules:      Data.DList.NonEmpty+                        Data.DList.NonEmpty.Unsafe+  other-modules:        Data.DList.NonEmpty.Internal+  ghc-options:          -Wall+  if impl(ghc >= 8.0)+    ghc-options:        -Wcompat++test-suite test+  default-language:     Haskell2010+  type:                 exitcode-stdio-1.0+  main-is:              Main.hs+  hs-source-dirs:       tests+  other-modules:        OverloadedStrings+  build-depends:        dlist-nonempty,+                        base,+                        Cabal,+                        QuickCheck >= 2.9 && < 2.11,+                        quickcheck-instances+  if !impl(ghc >= 8.0)+    build-depends:+                        semigroups >=0.18.2 && <0.19++benchmark bench+  default-language:     Haskell2010+  type:                 exitcode-stdio-1.0+  main-is:              Main.hs+  hs-source-dirs:       bench+  build-depends:        base,+                        base-compat,+                        dlist,+                        dlist-nonempty,+                        dlist-instances,+                        criterion >= 1.1.4.0 && <1.3+  if !impl(ghc >= 8.0)+    build-depends:+                        semigroups >=0.18.2 && <0.19
+ src/Data/DList/NonEmpty.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE CPP #-}+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+#endif++-- | Non-empty difference lists: a data structure for /O(1)/ append on non-empty lists.+module Data.DList.NonEmpty+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 800+  ( NonEmptyDList(Cons)+#else+  ( NonEmptyDList+#endif++  -- * Conversion+  , toNonEmpty+  , apply+  , toList+  , toDList+  , toEndo+  , toEndo'++  -- * Construction+  --+  -- | The O(1) functions.+  , fromNonEmpty+  , singleton+  , cons+  , snoc+  , append++  -- * Other functions+  , concat1+  , replicate+  , head+  , tail+  , unfoldr+  , map++#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708 && __GLASGOW_HASKELL__ < 800+  -- * Pattern Synonyms+  , pattern Cons+#endif++  ) where++import Prelude ()+import Data.DList.NonEmpty.Internal
+ src/Data/DList/NonEmpty/Internal.hs view
@@ -0,0 +1,268 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-} -- For the IsList (uses family) and IsString (~) instances+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+#endif++-- | Non-empty difference lists: a data structure for /O(1)/ append on non-empty lists.+module Data.DList.NonEmpty.Internal where++import Prelude ()+import Prelude.Compat hiding (concat, foldr, map, head, tail, replicate)++import Control.DeepSeq (NFData (..))+import Control.Monad+import Data.Function (on)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Monoid (Endo (..))+import Data.Semigroup (Semigroup(..))+import Data.String (IsString(..))++import qualified Data.List as List+import qualified Data.List.NonEmpty as NE+import qualified Data.Foldable as F+import qualified Data.DList as DList++-- semigroupoids+import Data.Functor.Apply (Apply (..))+import Data.Functor.Bind (Bind (..))+import Data.Functor.Alt (Alt (..))+import Data.Semigroup.Foldable (Foldable1 (..))+import Data.Semigroup.Traversable (Traversable1 (..))++#ifdef __GLASGOW_HASKELL__++import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,+                  readListPrecDefault)++#if __GLASGOW_HASKELL__ >= 708+import GHC.Exts (IsList)+-- This is for the IsList methods, which conflict with fromList, toList:+import qualified GHC.Exts+#endif++#endif++-- | A difference list is a function that, given a list, returns the original+-- contents of the difference list prepended to the given list.+--+-- Implemented as a newtype over @[a] -> 'NonEmpty' a@.+newtype NonEmptyDList a = NEDL { unNEDL :: [a] -> NonEmpty a }++-- | Convert a list to a dlist+fromNonEmpty :: NonEmpty a -> NonEmptyDList a+fromNonEmpty (x :| xs) = NEDL $ (x :|) . (xs ++)+{-# INLINE fromNonEmpty #-}++-- | Convert a dlist to a non-empty list+toNonEmpty :: NonEmptyDList a -> NonEmpty a+toNonEmpty = ($[]) . unNEDL+{-# INLINE toNonEmpty #-}++-- | Convert a dlist to a list+toList :: NonEmptyDList a -> [a]+toList = NE.toList . toNonEmpty+{-# INLINE toList #-}++-- | Convert to 'DList'.+--+-- /Note:/ @dlist@ doesn't expose internals, so this have to go through list.+toDList :: NonEmptyDList a -> DList.DList a+toDList = DList.fromList . toList+{-# INLINE toDList #-}++-- | Convert to representation of 'DList'.+toEndo :: NonEmptyDList a -> Endo [a]+toEndo ne = Endo (NE.toList . unNEDL ne)++-- | Convert to representation of 'DList'.+toEndo' :: NonEmptyDList a -> [a] -> [a]+toEndo' = appEndo . toEndo++#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+-- | A unidirectional pattern synonym using 'toList' in a view pattern and+-- matching on @x:xs@ such that you have the pattern @Cons x xs@+#if __GLASGOW_HASKELL__ >= 710+pattern Cons :: a -> [a] -> NonEmptyDList a+#endif+pattern Cons x xs <- (toNonEmpty -> x :| xs)+#endif++-- | Apply a dlist to a list to get the underlying non-empty list with an extension+apply :: NonEmptyDList a -> [a] -> NonEmpty a+apply = unNEDL++-- | Create dlist with a single element+singleton :: a -> NonEmptyDList a+singleton = NEDL . (:|)+{-# INLINE singleton #-}++-- | /O(1)/. Prepend a single element to a dlist+infixr `cons`+cons :: a -> NonEmptyDList a -> NonEmptyDList a+cons x xs = NEDL (NE.cons x . unNEDL xs)+{-# INLINE cons #-}++-- | /O(1)/. Append a single element to a dlist+infixl `snoc`+snoc :: NonEmptyDList a -> a -> NonEmptyDList a+snoc xs x = NEDL (unNEDL xs . (x:))+{-# INLINE snoc #-}++-- | /O(1)/. Append dlists+append :: NonEmptyDList a -> NonEmptyDList a -> NonEmptyDList a+append xs ys = NEDL (unNEDL xs . NE.toList . unNEDL ys)+{-# INLINE append #-}++-- | /O(spine)/. Concatenate dlists+concat1 :: NonEmpty (NonEmptyDList a) -> NonEmptyDList a+concat1 = sconcat+{-# INLINE concat1 #-}++-- | /O(n)/. Create a dlist of the given number of elements.+--+-- Always creates a list with at least one element.+replicate :: Int -> a -> NonEmptyDList a+replicate n x = NEDL $ \xs -> let go m | m <= 1 = x :| xs+                                     | otherwise = NE.cons x $ go (m-1)+                            in go n+{-# INLINE replicate #-}++-- | /O(n)/. Return the head of the dlist+head :: NonEmptyDList a -> a+head = NE.head . toNonEmpty++-- | /O(n)/. Return the tail of the dlist+tail :: NonEmptyDList a -> [a]+tail = NE.tail . toNonEmpty++-- | /O(n)/. Unfoldr for dlists+unfoldr :: (b -> (a, Maybe b)) -> b -> NonEmptyDList a+unfoldr pf b = case pf b of+    (a, Nothing) -> singleton a+    (a, Just b')  -> cons a (unfoldr pf b')++-- | /O(n)/. Map over difference lists.+map :: (a -> b) -> NonEmptyDList a -> NonEmptyDList b+map f = fromNonEmpty . fmap f . toNonEmpty+{-# INLINE map #-}++instance Eq a => Eq (NonEmptyDList a) where+  (==) = (==) `on` toList++instance Ord a => Ord (NonEmptyDList a) where+  compare = compare `on` toList++-- The Read and Show instances were adapted from Data.Sequence.++instance Read a => Read (NonEmptyDList a) where+#ifdef __GLASGOW_HASKELL__+  readPrec = parens $ prec 10 $ do+    Ident "fromNonEmpty" <- lexP+    dl <- readPrec+    return (fromNonEmpty dl)+  readListPrec = readListPrecDefault+#else+  readsPrec p = readParen (p > 10) $ \r -> do+    ("fromNonEmpty", s) <- lex r+    (dl, t) <- readsPrec 11 s+    return (fromNonEmpty dl, t)+#endif++instance Show a => Show (NonEmptyDList a) where+  showsPrec p dl = showParen (p > 10) $+    showString "fromNonEmpty " . showsPrec 11 (toNonEmpty dl)++instance Functor NonEmptyDList where+  fmap = map+  {-# INLINE fmap #-}++instance Applicative NonEmptyDList where+  pure = singleton+  {-# INLINE pure #-}+  (<*>) = ap++instance Monad NonEmptyDList where+  m >>= k+    -- = concat (toList (fmap k m))+    -- = (concat . toList . fromList . List.map k . toList) m+    -- = concat . List.map k . toList $ m+    -- = List.foldr append empty . List.map k . toList $ m+    -- = List.foldr (append . k) empty . toList $ m+   = concat1 . fmap k . toNonEmpty $ m+  {-# INLINE (>>=) #-}++  return = pure+  {-# INLINE return #-}++instance Foldable NonEmptyDList where+  fold = mconcat . toList+  {-# INLINE fold #-}++  foldMap f = F.foldMap f . toList+  {-# INLINE foldMap #-}++  foldr f x = List.foldr f x . toList+  {-# INLINE foldr #-}++  foldl f x = List.foldl f x . toList+  {-# INLINE foldl #-}++  foldr1 f = List.foldr1 f . toList+  {-# INLINE foldr1 #-}++  foldl1 f = List.foldl1 f . toList+  {-# INLINE foldl1 #-}++-- CPP: foldl', foldr' added to Foldable in 7.6.1+-- http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/release-7-6-1.html+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706+  foldl' f x = List.foldl' f x . toList+  {-# INLINE foldl' #-}++  foldr' f x = F.foldr' f x . toList+  {-# INLINE foldr' #-}+#endif++instance Traversable NonEmptyDList where+  traverse f = fmap fromNonEmpty . traverse f . toNonEmpty+  sequenceA  = fmap fromNonEmpty . sequenceA . toNonEmpty++instance NFData a => NFData (NonEmptyDList a) where+  rnf = rnf . toNonEmpty+  {-# INLINE rnf #-}++-- This is partial instance. Will fail on empty string.+instance a ~ Char => IsString (NonEmptyDList a) where+  fromString = fromNonEmpty . NE.fromList+  {-# INLINE fromString #-}++#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+instance IsList (NonEmptyDList a) where+  type Item (NonEmptyDList a) = a+  fromList = fromNonEmpty . NE.fromList+  {-# INLINE fromList #-}+  toList = toList+  {-# INLINE toList #-}+#endif++instance Semigroup (NonEmptyDList a) where+  (<>) = append+  {-# INLINE (<>) #-}++-------------------------------------------------------------------------------+-- semigroupoids+-------------------------------------------------------------------------------++instance Apply NonEmptyDList where (<.>) = (<*>)+instance Bind NonEmptyDList where (>>-) = (>>=)++instance Foldable1 NonEmptyDList where+  foldMap1 f = foldMap1 f . toNonEmpty++instance Traversable1 NonEmptyDList where+  traverse1 f = fmap fromNonEmpty . traverse1 f . toNonEmpty+  sequence1   = fmap fromNonEmpty . sequence1 . toNonEmpty++instance Alt NonEmptyDList where+  (<!>) = append
+ src/Data/DList/NonEmpty/Unsafe.hs view
@@ -0,0 +1,11 @@+-- | This module exports the internal representation of 'NonEmptyDList'.+--+-- Use with care. It's very easy to break the safe interface:+--+-- >>> let nedl = NEDL ((1 :|) . map (+1))+-- >>> nedl <> nedl+-- fromNonEmpty (1 :| [2])+--+module Data.DList.NonEmpty.Unsafe (NonEmptyDList (..)) where++import Data.DList.NonEmpty.Internal
+ tests/Main.hs view
@@ -0,0 +1,150 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE OverloadedLists #-} -- For the IsList test+#if __GLASGOW_HASKELL__ == 708+{-# LANGUAGE PatternSynonyms #-} -- For pattern synonym use only in GHC 7.8+#endif+#endif+++--------------------------------------------------------------------------------++module Main (main) where++--------------------------------------------------------------------------------++import Prelude hiding (concat, foldr, head, map, replicate, tail)+import qualified Data.List as List+import Test.QuickCheck+import Test.QuickCheck.Instances ()+import Test.QuickCheck.Function++import Data.DList.NonEmpty++import OverloadedStrings (testOverloadedStrings)++import Data.Semigroup (Semigroup(..))+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NE++--------------------------------------------------------------------------------++eqWith :: (Eq b, Show b) => (a -> b) -> (a -> b) -> a -> Property+eqWith f g x = f x === g x++eqOn :: (Eq b, Show b) => (a -> Bool) -> (a -> b) -> (a -> b) -> a -> Property+eqOn c f g x = c x ==> f x === g x++--------------------------------------------------------------------------------++prop_model :: NonEmpty Int -> Property+prop_model = eqWith id (toNonEmpty . fromNonEmpty)++prop_singleton :: Int -> Property+prop_singleton = eqWith (:|[]) (toNonEmpty . singleton)++prop_cons :: Int -> NonEmpty Int -> Property+prop_cons c = eqWith (NE.cons c) (toNonEmpty . cons c . fromNonEmpty)++prop_snoc :: NonEmpty Int -> Int -> Property+prop_snoc xs c = xs <> (c :| []) === toNonEmpty (snoc (fromNonEmpty xs) c)++prop_append :: NonEmpty Int -> NonEmpty Int -> Property+prop_append xs ys = xs <> ys === toNonEmpty (fromNonEmpty xs `append` fromNonEmpty ys)++prop_concat1 :: NonEmpty (NonEmpty Int) -> Property+prop_concat1 = eqWith sconcat (toNonEmpty . concat1 . fmap fromNonEmpty)++-- The condition reduces the size of replications and thus the eval time.+prop_replicate :: Int -> Int -> Property+prop_replicate n =+  eqOn (const (n < 100)) (rep n) (toNonEmpty . replicate n)+  where+    rep m x = x :| List.replicate (m - 1) x++prop_head :: NonEmpty Int -> Property+prop_head = eqWith NE.head (head . fromNonEmpty)++prop_tail :: NonEmpty Int -> Property+prop_tail = eqWith NE.tail (tail . fromNonEmpty)++prop_unfoldr :: Fun Int (Int, Maybe Int) -> Int -> Int -> Property+prop_unfoldr (Fun _ f) n =+  eqOn (const (n >= 0)) (NE.take n . NE.unfoldr f) (NE.take n . toNonEmpty . unfoldr f)++prop_map :: Fun Int Int -> NonEmpty Int -> Property+prop_map (Fun _ f) = eqWith (fmap f) (toNonEmpty . map f . fromNonEmpty)++prop_map_fusion :: (Int -> Int) -> (a -> Int) -> NonEmpty a -> Property+prop_map_fusion f g =+  eqWith (fmap f . fmap g) (toNonEmpty . map f . map g . fromNonEmpty)++prop_show_read :: [Int] -> Property+prop_show_read = eqWith id (read . show)++prop_read_show :: NonEmpty Int -> Property+prop_read_show x = eqWith id (show . f . read) $ "fromNonEmpty (" <> show x <> ")"+  where+    f :: NonEmptyDList Int -> NonEmptyDList Int+    f = id++#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+-- | Test that the IsList instance methods compile and work with simple lists+prop_IsList :: Property+prop_IsList = test_fromNonEmpty [1,2,3] .&&. test_toNonEmpty (fromNonEmpty [1,2,3])+  where+    test_fromNonEmpty, test_toNonEmpty :: NonEmptyDList Int -> Property+    test_fromNonEmpty x = x === fromNonEmpty [1,2,3]+    test_toNonEmpty [1,2,3] = property True+    test_toNonEmpty _       = property False++prop_patterns :: NonEmpty Int -> Property+prop_patterns xs = case fromNonEmpty xs of+  Cons y ys -> xs === (y:|ys)+  _         -> property False+#endif++prop_Semigroup_append :: NonEmpty Int -> NonEmpty Int -> Property+prop_Semigroup_append xs ys = xs <> ys === toNonEmpty (fromNonEmpty xs <> fromNonEmpty ys)++prop_Semigroup_sconcat :: NonEmpty (NonEmpty Int) -> Property+prop_Semigroup_sconcat xs = sconcat xs === toNonEmpty (sconcat (fmap fromNonEmpty xs))++prop_Semigroup_stimes :: Int -> NonEmpty Int -> Property+prop_Semigroup_stimes n xs = n >=1 ==>+    stimes n xs === toNonEmpty (stimes n (fromNonEmpty xs))++--------------------------------------------------------------------------------++props :: [(String, Property)]+props =+  [ ("model",             property prop_model)+  , ("singleton",         property prop_singleton)+  , ("cons",              property prop_cons)+  , ("snoc",              property prop_snoc)+  , ("append",            property prop_append)+  , ("concat1",           property prop_concat1)+  , ("replicate",         property prop_replicate)+  , ("head",              property prop_head)+  , ("tail",              property prop_tail)+  , ("unfoldr",           property prop_unfoldr)+  , ("map",               property prop_map)+  , ("map fusion",        property (prop_map_fusion (+1) (+1)))+  , ("read . show",       property prop_show_read)+  , ("show . read",       property prop_read_show)+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+  , ("IsList",            property prop_IsList)+  , ("patterns",          property prop_patterns)+#endif+  , ("Semigroup <>",      property prop_Semigroup_append)+  , ("Semigroup sconcat", property prop_Semigroup_sconcat)+  , ("Semigroup stimes",  property prop_Semigroup_stimes)+  ]++--------------------------------------------------------------------------------++main :: IO ()+main = do+  testOverloadedStrings+  quickCheck $ conjoin $ fmap (uncurry label) props
+ tests/OverloadedStrings.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE OverloadedStrings #-}++module OverloadedStrings (testOverloadedStrings) where++import Data.DList.NonEmpty++testOverloadedStrings :: IO ()+testOverloadedStrings = print $ "OverloadedStrings:" `append` " success"