spl / dlist Goto Github PK
View Code? Open in Web Editor NEWDifference lists in Haskell
Home Page: https://hackage.haskell.org/package/dlist
License: BSD 3-Clause "New" or "Revised" License
Difference lists in Haskell
Home Page: https://hackage.haskell.org/package/dlist
License: BSD 3-Clause "New" or "Revised" License
tests/DListProperties.hs:70:31: warning: [GHC-63394] [-Wx-partial]
In the use of ‘head’
(imported from Data.List, but defined in GHC.List):
"This is a partial function, it throws an error on empty lists. Use pattern matching or Data.List.uncons instead. Consider refactoring to use Data.List.NonEmpty."
|
70 | prop_head = eqOn (not . null) List.head (head . fromList)
| ^^^^^^^^^
tests/DListProperties.hs:73:31: warning: [GHC-63394] [-Wx-partial]
In the use of ‘tail’
(imported from Data.List, but defined in GHC.List):
"This is a partial function, it throws an error on empty lists. Replace it with drop 1, or use pattern matching or Data.List.uncons instead. Consider refactoring to use Data.List.NonEmpty."
|
73 | prop_tail = eqOn (not . null) List.tail (tail . fromList)
| ^^^^^^^^^
It seems that the use of head
and tail
here is intended, so maybe just switch off the warning.
Do you mind to have the Traversable
instance for DList
?
I am currently using the following custom traverse
function:
traverseDList :: (Applicative f) => (a -> f b) -> DList a -> f (DList b)
traverseDList f = fmap DL.fromList . traverse f . DL.toList
I could make a PR if you think that is a desired addition to the library 🙂
Semigroup
will be in base
from GHC >= 8.0 (GHC #10365). We should now probably add an instance for it, since we can do it without adding another dependency. This may also involve revisiting #11.
These are useful functions to have, especially when DList is being used in conjunction with a Writer, or for the purpose of logging. If there's not any reason preventing these from being added may I make a pull request?
Building from master i get this:
$ stack test --resolver nightly-2016-07-29
dlist-0.8: build (lib + test)
Preprocessing library dlist-0.8...
Preprocessing test suite 'test' for dlist-0.8...
[2 of 2] Compiling Main ( tests/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/test/test-tmp/Main.o )
/Users/adam/repos/3rd/dlist/tests/Main.hs:150:27: error:
• No instance for (Arbitrary (NonEmpty [Int]))
arising from a use of ‘property’
• In the expression: property prop_Semigroup_sconcat
In the expression:
("Semigroup sconcat", property prop_Semigroup_sconcat)
In the expression:
[("model", property prop_model), ("empty", property prop_empty),
("singleton", property prop_singleton),
("cons", property prop_cons), ....]
Progress: 1/2
-- While building package dlist-0.8 using:
/Users/adam/.stack/setup-exe-cache/x86_64-osx/setup-Simple-Cabal-1.24.0.0-ghc-8.0.1 --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.0.0 build lib:dlist test:test --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
And building from the 0.8 tarball:
tests/Main.hs:24:1: error:
Failed to load interface for ‘OverloadedStrings’
Use -v to see a list of the files searched for.
I read through Haddocks & then went to articles that explain DList
, as http://h2.jaguarpaw.co.uk/posts/demystifying-dlist/.
Then I added benchmarks to the comparison repo to see "real" results.
Only in the end I see that DList
has a tutorial in the readme.md
.
Also note that linked article is named "demystifying DList", which implied that DList was considered a mystery when the article was written. Mentioning good 3rd party articles in the docs also can be a cheap efficient way of providing info, if only just to give reassurance that 3rd party article is viable & may give additional angles if reader did not grokked the documentation.
According to Travis-CI, dlist
does not build with GHC versions 7.0, 7.2, and 7.4.
Notifying so authors can check that DList
is represented properly.
& so authors are able, if needed, to give commentary:
Hey, thanks for this library!
I was looking at the implementation and was wondering if there is a specific reason to use a hand-written implementation for stimes
instead of Data.Semigroup.stimesMonoid
. If I look at it correctly stimesMonoid
uses only a logarithmic number of (<>)
and would be preferable to the current implementation. If this is case I can make a pull-request.
DList a
is isomorphic to [a]
via fromList
/toList
, but [a] -> [a]
is not isomorphic to [a]
. That is, all lists are dlists, and all dlists are lists only if there is no way to construct a y :: DList a
from an "unsafe" x :: [a] -> [a]
.
Currently, the library exports the constructor DL
and deconstructor unDL
which allows the construction of unsafe dlist values. Consider this GHCi session:
*Data.DList> let x = DL $ \z -> z ++ z
*Data.DList> toList x
[]
*Data.DList> fromList $ toList x
Data.DList.fromList []
The values of x
and toList x
are clearly not isomorphic. When used:
*Data.DList> append x (singleton 'a')
Data.DList.fromList "aa"
*Data.DList> append (fromList $ toList x) (singleton 'a')
Data.DList.fromList "a"
DList
was abstract early on. I don't know why it was changed.
To preserve the isomorphism, I think DList
should be an abstract type and the constructor and deconstructor should be removed from the export list.
This warning can be fixed in a backwards-compatible way by adding TypeOperators
to default-extensions:
in the .cabal
file.
Building library for dlist-1.0..
[1 of 5] Compiling Data.DList.Internal ( Data/DList/Internal.hs, dist/build/Data/DList/Internal.o, dist/build/Data/DList/Internal.dyn_o )
Data/DList/Internal.hs:642:12: warning: [-Wtype-equality-requires-operators]
The use of ‘~’ without TypeOperators
will become an error in a future GHC release.
Suggested fix: Perhaps you intended to use TypeOperators
|
642 | instance a ~ Char => IsString (DList a) where
| ^
[2 of 5] Compiling Data.DList ( Data/DList.hs, dist/build/Data/DList.o, dist/build/Data/DList.dyn_o )
[3 of 5] Compiling Data.DList.DNonEmpty.Internal ( Data/DList/DNonEmpty/Internal.hs, dist/build/Data/DList/DNonEmpty/Internal.o, dist/build/Data/DList/DNonEmpty/Internal.dyn_o )
Data/DList/DNonEmpty/Internal.hs:459:12: warning: [-Wtype-equality-requires-operators]
The use of ‘~’ without TypeOperators
will become an error in a future GHC release.
Suggested fix: Perhaps you intended to use TypeOperators
|
459 | instance a ~ Char => IsString (DNonEmpty a) where
| ^
Travis-CI reports a failure when attempting to build dlist
with GHC 6.12.3:
$ export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}') ; cd dist/; if [ -f "$SRC_TGZ" ]; then cabal-1.18 install "$SRC_TGZ"; else echo "expected '$SRC_TGZ' not found"; exit 1; fi
Warning: Falling back to topdown solver for GHC < 7.
Resolving dependencies...
Configuring dlist-0.5...
Failed to install dlist-0.5
Last 10 lines of the build log ( /home/travis/.cabal/logs/dlist-0.5.log ):
cabal-1.18: Error: some packages failed to install:
dlist-0.5 failed during the configure step. The exception was:
user error (The package 'dlist' requires Cabal library version -any && >=1.9.2
but no suitable version is installed.)
I'm not sure what the problem is. I don't even know if it should be fixed. Putting this here for the record.
Make a set of (micro-)benchmarks demonstrating the performance of dlist over lists with and without left-nested appends. Include Eq
, Ord
, and Show
instances which use toList
.
On current master, cabal test
puts the following errors into the log:
*** Failed! Exception: 'Prelude.read: no parse' (after 1 test):
0 :| []
fromList "OverloadedStrings for DList: success"
fromNonEmpty 'O' :| "verloadedStrings for DNonEmpty: success"
(However, the final result is printed as Test suite test: PASS
.)
Source location:
dlist/tests/OverloadedStrings.hs
Lines 26 to 31 in 157a97d
The usual assumption for pure data structures in Haskell is that the documented time bounds may be amortized, but that amortization must hold up under persistent use. That is not true for dlist
. snoc
and head
are both documented as being O(1)
, and yet the following program runs far longer than I would ever want to wait. Swapping in Data.Sequence
for DList
lets this run quickly.
import qualified Data.DList as D
import Data.DList (DList)
import Data.Foldable
blob :: DList Int
blob = foldl' D.snoc mempty [1..10^7]
main :: IO ()
main = print $ sum [ D.head (blob `D.snoc` a) | a <- [1..10^6 :: Int]]
I think the best approach is likely to document that DList
s are intended to be used in an affine/linear fashion, and that the bounds are only valid in that context.
Implement pattern synonyms for DList
in GHC >= 7.8.
Currently the main info is in fromList
Lines 104 to 136 in 1793a5e
This paragraph:
If you find yourself doing some form of the following you may not be taking advantage of the 'DList' representation and library:
fromList . f . toList
More likely, you will convert from a list, perform some operation on the 'DList', and convert back to a list:
toList . g . fromList
fromList :: [a] -> DList a
fromList = UnsafeDList . (++)
"If you find yourself doing some form of the following" implies that everything that follows - is counterproductive. & logically both fromList . f . toList
& toList . g . fromList
for simple things are counterproductive. & "following" statement opens - and never stops, never says where examples & "following" stops & it does not even have a .
at the end of sentences - so that means "everything that follows".
"If you find yourself doing some form of the following ... More likely, you will convert ..." - what does that mean = it is an ad hominem probabilistic characteristic, not a statement or explanation, moreover it applies things to me and not to a library or compiler. It not forgot to mention me in the docs, but forgot to mention if the way discussed there is recommended, or as "following" implies - just as counterproductive. Dwelling on ad hominems you
we
so much - to show a trend in the documentation of use those easy escape words as diversions, instead of the description of the process & objects involved. If to just remove personal directioning from docs - they suddenly both shorter & understandable.
As:
'fromList . f . toList' - does not be take advantage of the 'DList'.
'toList . g . fromList' - takes advantage of the 'DList' optimized operations.
suddenly text 2 times shorter & clear.
Moreover - that paragraph can be removed entirely as tautology - of course doing operations with other type & functions - is not using DList
.
Having O
notation & stating from/toList
costs is enough to infer where it is useful.
I vaguely remember reading about DList
directions of conversion, but it was years ago & do not remember if anisotropy (directional properties) came out being imaginary or real, if it is stated clearly in the doc - users would not need to remember it from years ago & would not get puzzled.
Hello, I'm getting this warning for a pattern usage like:
foo :: DList a -> IO ()
foo Nil = putStrLn "empty!"
foo (Cons x xs) = print $ x:xs
warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘foo’:
Patterns not matched: _
My understanding using pattern synonyms, is that the implementer needs to tell the compiler which pattern set should be considered as complete:
{-# COMPLETE Nil, Cons #-}
Would you accept a PR for that?
For some reason, the docs show that DList
is defined with data
. However, it is actually done with newtype
.
The new Monad
instance does not have the method fail
. That has been moved exclusively to MonadFail
in ghc-8.8.1
.
I tried building dlist
with the alpha release of the ghc-8.8.1
and the current version results in the following error:
Configuring microlens-0.4.10...
Preprocessing library for microlens-0.4.10..
Building library for microlens-0.4.10..
[1 of 4] Compiling Lens.Micro.Type ( src/Lens/Micro/Type.hs, .stack-work/dist/x86_64-linux/Cabal-2.5.0.0/build/Lens/Micro/Type.o )
[2 of 4] Compiling Lens.Micro.Internal ( src/Lens/Micro/Internal.hs, .stack-work/dist/x86_64-linux/Cabal-2.5.0.0/build/Lens/Micro/Internal.o )
[3 of 4] Compiling Lens.Micro ( src/Lens/Micro.hs, .stack-work/dist/x86_64-linux/Cabal-2.5.0.0/build/Lens/Micro.o )
/tmp/stack7255/microlens-0.4.10/src/Lens/Micro.hs:1416:5: error:
‘fail’ is not a (visible) method of class ‘Monad’
|
1416 | fail str = StateT $ \ _ -> fail str
| ^^^^
/tmp/stack7255/microlens-0.4.10/src/Lens/Micro.hs:1417:16: error:
The INLINE pragma for ‘fail’ lacks an accompanying binding
(The INLINE pragma must be given where ‘fail’ is declared)
|
1417 | {-# INLINE fail #-}
|
It should be simple enough to fix with some use of the C pre-processor.
Oops! Seems like I removed things that I shouldn't have in test.yml
with #110. Too much enthusiasm and too little oversight, I suppose. Add it back!
It should be possible to access last in O(1)
.
bench
job needs to be faster, and it seems like installing dependencies is what slows it down.In 1.0, the function tail
changed to DList a -> [a]
, motivated by the removal of the recursor list
.
However, what speaks against the following definition?
tail :: DList a -> DList a
tail (UnsafeDList f) = UnsafeDList (Data.List.tail . f)
This would be a proper efficient tail
function for DList
.
The new tail
(dlist-1.0) leaves the realm of DList
s, so it seems it is already subsumed by Data.List.tail . toList
.
Originally posted by @andreasabel in #69 (comment)
Should be easy to add, and they are useful for debugging space leaks.
I'd like to use this library, but in order to implement something (basically I need to lift a function [a] -> [a] to a DList a -> DList a function... I think I need the DL constructor. I think what I want to do is this:
myLift f = DL $ f . unDL
Unfortunately DL
and unDL
don't seem to be exposed. unDL
is indirectly exposed with apply
, but I don't see DL
isn't exported by the module.
Is there a good way to efficiently do what I want to do? Without access to the constructor? Admittedly, I'm not much of a wizard at analyzing Haskell performance, so it's possible I'm missing something, but maybe it would make sense to expose DL
in an internal module or something?
This relates to this old PR: #4
I totally agree with not exporting it by default, but if I want to be unsafe, having the option would be nice :).
https://hackage.haskell.org/package/dlist-1.0 lists a module Data.DList.Unsafe
, but I cannot click it to access its documentation.
Figure out why the GitHub Actions are failing. In particular, look at the 7.10 job.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.