Skip to content

Commit bc523b8

Browse files
authored
Merge pull request #8 from danslapman/refactor/sequence
Use Data.Sequence instead of Deque
2 parents 4a36b05 + 6fd24c0 commit bc523b8

File tree

11 files changed

+70
-81
lines changed

11 files changed

+70
-81
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ jobs:
2828
stack-no-global: true
2929
enable-stack: true
3030
stack-version: 'latest'
31+
- run: stack test
3132
- run: stack --local-bin-path target install
33+
if: ${{ startsWith(github.ref, 'refs/tags/') }}
3234
- uses: svenstaro/upload-release-action@v2
3335
with:
3436
repo_token: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.vscode/
12
dist
23
dist-*
34
cabal-dev
@@ -23,3 +24,4 @@ cabal.project.local~
2324
json2csv.cabal
2425
stack.yaml.lock
2526
*/target/**
27+
.repos

app/Main.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import qualified Data.HashMap.Strict as HM
1313
import Data.HashSet (HashSet, empty, intersection, null, union)
1414
import qualified Data.HashSet as HS (toList)
1515
import Data.IORef
16+
import Data.Sequence (Seq)
17+
import qualified Data.Sequence as Seq (fromList)
1618
import Data.Text (Text, intercalate)
1719
import qualified Data.Text.IO as TIO
18-
import Deque.Strict (Deque)
19-
import DequeUtils (uniq)
20-
import GHC.Exts (fromList)
2120
import Json2Csv
2221
import Options.Applicative hiding (empty)
2322
import Options.Applicative.Text
2423
import Schema
24+
import SequenceUtils (uniq)
2525
import System.IO
2626
import System.ProgressBar
2727
import Prelude hiding (foldl, foldl', map, null, sequence)
@@ -75,7 +75,7 @@ main = do
7575
(parseAndWriteEntry mkSepString flat schema columns hIn hOut)
7676
incProgress pb 1
7777

78-
computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Deque JsonPath, Int)
78+
computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Seq JsonPath, Int)
7979
computeHeaderMultiline combine handle = do
8080
currentLineNumber <- newIORef (0 :: Int)
8181
pathSet <- newIORef (empty :: HashSet JsonPath)
@@ -90,9 +90,9 @@ computeHeaderMultiline combine handle = do
9090
modifyIORef' pathSet (combine header)
9191
pathes <- readIORef pathSet
9292
numberOfLines <- readIORef currentLineNumber
93-
return (fromList . HS.toList $ pathes, numberOfLines)
93+
return (Seq.fromList . HS.toList $ pathes, numberOfLines)
9494

95-
parseAndWriteEntry :: (Deque Text -> Text) -> Bool -> JsonSchema -> Deque Text -> Handle -> Handle -> IO ()
95+
parseAndWriteEntry :: (Seq Text -> Text) -> Bool -> JsonSchema -> Seq Text -> Handle -> Handle -> IO ()
9696
parseAndWriteEntry mkSepString flat schema columns hIn hOut = do
9797
line <- LBS.fromStrict <$> BS.hGetLine hIn
9898
let (Just parsed) = decode line :: Maybe Value

opl.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
b.$.value;a
2+
field b2;field a0
3+
field b xxx;field a0
4+
field b1;field a1
5+
field b2;field a2
6+
field b xxx;field a2

package.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ dependencies:
2626
- bytestring
2727
- aeson
2828
- vector
29+
- containers
2930
- unordered-containers
3031
- lens
3132
- lens-aeson
3233
- monad-loops
33-
- deque
3434
- hashable
3535
- deepseq
3636
- optparse-applicative
@@ -68,3 +68,4 @@ tests:
6868
- -fwarn-unused-imports
6969
dependencies:
7070
- json2csv
71+
- HUnit

src/DequePatterns.hs

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/DequeUtils.hs

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/Json2Csv.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ import qualified Data.Aeson.Key as JK
77
import qualified Data.Aeson.KeyMap as KM
88
import Data.HashSet
99
import Data.Maybe (mapMaybe)
10+
import Data.Sequence ((<|))
1011
import Data.Text (Text, pack)
1112
import qualified Data.Vector as V
12-
import Deque.Strict (cons)
1313
import HashSetUtils
1414
import Schema
1515
import TextShow hiding (singleton)
1616
import Prelude hiding (concatMap, foldl, join, map, null)
1717

1818
prepend :: JsonPathElement -> HashSet JsonPath -> HashSet JsonPath
1919
prepend prefix s | null s = singleton $ pure prefix
20-
prepend prefix path = map (prefix `cons`) path
20+
prepend prefix path = map (prefix <|) path
2121

2222
nonEmptyJ :: Value -> Bool
2323
nonEmptyJ Null = False

src/Schema.hs

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ import Data.HashMap.Strict (HashMap)
1515
import Data.HashMap.Strict qualified as HM
1616
import Data.Hashable
1717
import Data.Maybe hiding (mapMaybe)
18+
import Data.Sequence
1819
import Data.Text (Text, intercalate)
1920
import Data.Typeable (Typeable)
20-
import Deque.Strict
21-
import DequePatterns
22-
import DequeUtils
23-
import GHC.Exts (fromList)
2421
import GHC.Generics (Generic)
22+
import SequenceUtils
2523
import Prelude hiding (any, foldl, foldl', head)
2624

2725
data JsonPathElement
@@ -33,63 +31,63 @@ instance Hashable JsonPathElement
3331

3432
instance NFData JsonPathElement
3533

36-
type JsonPath = Deque JsonPathElement
34+
type JsonPath = Seq JsonPathElement
3735

3836
data JsonSchemaTree
39-
= PathNode JsonPathElement (Deque JsonSchemaTree)
37+
= PathNode JsonPathElement (Seq JsonSchemaTree)
4038
| PathEnd
4139
deriving (Eq, Show, Typeable)
4240

43-
type JsonSchema = Deque JsonSchemaTree
41+
type JsonSchema = Seq JsonSchemaTree
4442

4543
hasSameRoot :: JsonPath -> JsonSchemaTree -> Bool
4644
hasSameRoot path tree = case (tree, path) of
47-
(PathNode el _, h :|| _) | el == h -> True
45+
(PathNode el _, h :<| _) | el == h -> True
4846
otherwise -> False
4947

5048
toSchemaTree :: JsonPath -> JsonSchemaTree
5149
toSchemaTree =
5250
\case
53-
D_ -> PathEnd
54-
root :|| path -> PathNode root $ pure $ toSchemaTree path
51+
Empty -> PathEnd
52+
root :<| path -> PathNode root $ pure $ toSchemaTree path
5553

5654
(#+) :: JsonSchema -> JsonPath -> JsonSchema
5755
(#+) schema path =
5856
let append path tree = case (tree, path) of
59-
(t, D_) -> t
60-
(PathNode el D_, h :|| tail)
57+
(t, Empty) -> t
58+
(PathNode el Empty, h :<| tail)
6159
| el == h ->
6260
PathNode el $ pure $ toSchemaTree tail
63-
(PathNode el branches, h :|| tail)
61+
(PathNode el branches, h :<| tail)
6462
| el == h ->
6563
PathNode el $ uniq $ branches #+ tail
6664
(PathEnd, path) -> toSchemaTree path
6765
(t, _) -> t
6866
in if any (hasSameRoot path) schema
6967
then append path <$> schema
70-
else toSchemaTree path `snoc` schema
68+
else schema |> toSchemaTree path
7169

72-
toSchema :: Deque JsonPath -> JsonSchema
70+
toSchema :: Seq JsonPath -> JsonSchema
7371
toSchema = foldl' (#+) empty
7472

7573
data JsonValueTree
76-
= ValueRoot JsonPathElement (Deque JsonValueTree)
74+
= ValueRoot JsonPathElement (Seq JsonValueTree)
7775
| SingleValue JsonPathElement Value
78-
| ValueArray (Deque Value)
79-
| TreeArray (Deque (Deque JsonValueTree))
76+
| ValueArray (Seq Value)
77+
| TreeArray (Seq (Seq JsonValueTree))
8078
deriving (Eq, Show, Typeable)
8179

82-
type JsonTree = Deque JsonValueTree
80+
type JsonTree = Seq JsonValueTree
8381

8482
extract :: JsonSchema -> Value -> JsonTree
8583
extract schema value =
8684
let extractTree v schemaTree =
8785
case schemaTree of
8886
PathEnd -> Nothing
89-
(PathNode el (PathEnd :|| D_)) ->
87+
(PathNode el (PathEnd :<| Empty)) ->
9088
case el of
9189
Key k -> SingleValue el <$> v ^? (key $ fromText k)
92-
Iterator -> ValueArray <$> (maybeNeq $ fromList $ v ^.. values)
90+
Iterator -> ValueArray <$> (maybeNes $ fromList $ v ^.. values)
9391
(PathNode el@(Key k) children) ->
9492
let keyValue = (v ^? (key $ fromText k))
9593
childrenExtractors = flip extractTree <$> children
@@ -99,20 +97,20 @@ extract schema value =
9997
let nodeValues = fromList $ v ^.. values
10098
childrenExtractors = flip extractTree <$> children
10199
nodeTrees = (\val -> mapMaybe id $ ($ val) <$> childrenExtractors) <$> nodeValues
102-
in TreeArray <$> maybeNeq nodeTrees
100+
in TreeArray <$> maybeNes nodeTrees
103101
in mapMaybe id $ (extractTree value <$> schema)
104102

105-
genMaps :: Bool -> JsonPath -> JsonValueTree -> Deque (HashMap Text Value)
103+
genMaps :: Bool -> JsonPath -> JsonValueTree -> Seq (HashMap Text Value)
106104
genMaps flat jp jvt =
107105
case (flat, jvt) of
108-
(_, ValueRoot jpe trees) -> xfold $ genMaps flat (jpe `snoc` jp) <$> trees
109-
(_, SingleValue jpe value) -> pure $ HM.singleton (jsonPathText $ jpe `snoc` jp) value
110-
(False, ValueArray values) -> HM.singleton (jsonPathText (Iterator `snoc` jp)) <$> values
106+
(_, ValueRoot jpe trees) -> xfold $ genMaps flat (jp |> jpe) <$> trees
107+
(_, SingleValue jpe value) -> pure $ HM.singleton (jsonPathText $ jp |> jpe) value
108+
(False, ValueArray values) -> HM.singleton (jsonPathText (jp |> Iterator)) <$> values
111109
(True, ValueArray values) -> HM.singleton (jsonPathText jp) <$> values
112-
(False, TreeArray trees) -> trees >>= (xfold . (genMaps flat (Iterator `snoc` jp) <$>))
110+
(False, TreeArray trees) -> trees >>= (xfold . (genMaps flat (jp |> Iterator) <$>))
113111
(True, TreeArray trees) -> trees >>= (xfold . (genMaps flat jp <$>))
114112

115-
generateTuples :: Bool -> JsonTree -> Deque (HashMap Text Value)
113+
generateTuples :: Bool -> JsonTree -> Seq (HashMap Text Value)
116114
generateTuples flat jTree = xfold $ genMaps flat empty <$> jTree
117115

118116
jsonPathText :: JsonPath -> Text
@@ -131,13 +129,13 @@ dropIterators jpath =
131129
Key k -> Just $ Key k
132130
Iterator -> Nothing
133131

134-
xseq :: (a -> a -> a) -> Deque a -> Deque a -> Deque a
135-
xseq _ va D_ = va
136-
xseq _ D_ vb = vb
132+
xseq :: (a -> a -> a) -> Seq a -> Seq a -> Seq a
133+
xseq _ va Empty = va
134+
xseq _ Empty vb = vb
137135
xseq f va vb = do
138136
a <- va
139137
b <- vb
140138
return $ f a b
141139

142-
xfold :: Deque (Deque (HashMap Text Value)) -> Deque (HashMap Text Value)
140+
xfold :: Seq (Seq (HashMap Text Value)) -> Seq (HashMap Text Value)
143141
xfold = foldl' (xseq HM.union) empty

src/SequenceUtils.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module SequenceUtils where
2+
3+
import Data.Foldable (find, toList)
4+
import qualified Data.List as L
5+
import qualified Data.Maybe as Mb (mapMaybe)
6+
import Data.Sequence
7+
import Prelude hiding (concat, elem, foldl, foldl', foldl1, mapM, null, (++))
8+
9+
maybeNes :: Seq a -> Maybe (Seq a)
10+
maybeNes = find (not . null) . Just
11+
12+
uniq :: Eq a => Seq a -> Seq a
13+
uniq = fromList . L.nub . toList
14+
15+
mapMaybe :: (a -> Maybe b) -> Seq a -> Seq b
16+
mapMaybe _ Empty = empty
17+
mapMaybe pred dq =
18+
fromList . Mb.mapMaybe pred . toList $ dq

0 commit comments

Comments
 (0)