Skip to content

Commit 89563d9

Browse files
committed
Adding untyped
1 parent 253bf03 commit 89563d9

File tree

7 files changed

+242
-117
lines changed

7 files changed

+242
-117
lines changed

bower.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"purescript-generics-rep": "^6.0.0",
1717
"purescript-filterable": "^3.0.1",
1818
"purescript-record": "^1.0.0",
19-
"purescript-record-extra": "^1.0.0"
19+
"purescript-record-extra": "^1.0.0",
20+
"purescript-argonaut-core": "^4.0.1",
21+
"purescript-strings": "^4.0.0"
2022
},
2123
"devDependencies": {
2224
"purescript-psci-support": "^4.0.0"

src/Data/DataFrame.purs

+36-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,24 @@ import Prelude
44

55
import Data.Compactable (class Compactable, separate)
66
import Data.Filterable (class Filterable, partitionMap)
7+
import Data.Foldable (maximum)
78
import Data.Function (on)
89
import Data.Generic.Rep (class Generic)
9-
import Data.List (catMaybes, mapMaybe, partition)
10+
import Data.List (catMaybes, head, mapMaybe, partition, sortBy, take, transpose)
1011
import Data.List (filter) as List
1112
import Data.List.Types (List)
13+
import Data.Map (Map)
14+
import Data.Map (toUnfoldable) as Map
15+
import Data.Maybe (fromMaybe, maybe)
16+
import Data.Monoid (power)
1217
import Data.Newtype (class Newtype, over, unwrap, wrap)
18+
import Data.NonEmpty (NonEmpty(..))
19+
import Data.String (length)
20+
import Data.String.NonEmpty (NonEmptyString)
21+
import Data.String.NonEmpty (length) as NES
22+
import Data.Tuple (fst, snd)
23+
import Data.Tuple.Nested ((/\), type (/\))
24+
import Types (Row, Column)
1325

1426
newtype DataFrame a = DataFrame (List a)
1527

@@ -34,3 +46,26 @@ instance filterableDF :: Filterable DataFrame where
3446
filterMap f = over DataFrame (mapMaybe f)
3547
partition f = (\{yes, no} -> {yes: wrap yes, no: wrap no}) <<< partition f <<< unwrap
3648
partitionMap f = (\{left, right} -> {left: wrap left, right: wrap right}) <<< partitionMap f <<< unwrap
49+
50+
instance showUntypedDataFrame :: Show a => Show (DataFrame (Map NonEmptyString a)) where
51+
show =
52+
unwrap >>>
53+
take 10 >>>
54+
map (Map.toUnfoldable >>> sortBy (compare `on` fst)) >>>
55+
transpose >>>
56+
map drawColumn >>>
57+
placeSideToSide
58+
where
59+
drawColumn :: List (NonEmptyString /\ a) -> List String
60+
drawColumn xs =
61+
map
62+
(snd >>> padTo (max (maxLengthOfValues xs) (maybe 0 (fst >>> show >>> length) (head xs))))
63+
xs
64+
maxLengthOfValues :: List (NonEmptyString /\ a) -> Int
65+
maxLengthOfValues = map (snd >>> show >>> length) >>> maximum >>> fromMaybe 0
66+
padTo :: Int -> a -> String
67+
padTo i a =
68+
let pad = power " " $ (i - length (show a)) / 2
69+
in pad <> show a <> pad
70+
placeSideToSide :: List (List String) -> String
71+
placeSideToSide _ = "foo"

src/Data/Query.purs

+1-106
Original file line numberDiff line numberDiff line change
@@ -7,123 +7,18 @@ import Control.Monad.Reader.Trans (ReaderT)
77
import Data.DataFrame (DataFrame(..))
88
import Data.Filterable (filter) as Filterable
99
import Data.Foldable (foldr)
10-
import Data.Function (on)
11-
import Data.List (List, sortBy, (:))
10+
import Data.List (List, (:))
1211
import Data.Map (alter, empty, toUnfoldable) as Map
1312
import Data.Maybe (Maybe(..), maybe)
1413
import Data.Newtype (over)
15-
import Data.Ordering (invert)
16-
import Data.Symbol (class IsSymbol, SProxy(..))
1714
import Data.Tuple (snd)
1815
import Data.Tuple.Nested (type (/\))
19-
import Prim.Row (class Cons, class Lacks)
20-
import Prim.RowList (class RowToList, Cons, Nil, kind RowList)
21-
import Record (get, insert)
22-
import Record (insert, rename) as R
23-
import Type.Row (class ListToRow, RLProxy(..), RProxy)
2416

2517
type Query m a b = ReaderT (DataFrame a) m (DataFrame b)
2618

2719
filter :: m a. Monad m => (a -> Boolean) -> Query m a a
2820
filter f = asks (Filterable.filter f)
2921

30-
arrange
31-
:: m sym a rec without
32-
. Ord a
33-
=> Monad m
34-
=> IsSymbol sym
35-
=> Lacks sym without
36-
=> Cons sym a without rec
37-
=> SProxy sym
38-
-> Boolean
39-
-> Query m ({|rec}) ({|rec})
40-
arrange proxy asc = asks (over DataFrame $ sortBy (comp `on` (get proxy)))
41-
where
42-
comp :: a -> a -> Ordering
43-
comp a = if asc then compare a else invert <<< compare a
44-
45-
pull
46-
:: m sym a rec without' without
47-
. Monad m
48-
=> IsSymbol sym
49-
=> Lacks sym without
50-
=> Lacks sym without'
51-
=> Cons sym a without rec
52-
=> SProxy sym
53-
-> Query m {|rec} a
54-
pull proxy = asks (over DataFrame $ map ( get proxy))
55-
56-
class RowSubset (row :: # Type) (xs :: RowList) (subrow :: # Type) | row xs -> subrow where
57-
subsetImpl :: RLProxy xs -> {|row} -> {|subrow}
58-
59-
instance nilRowSubset :: RowSubset row Nil () where subsetImpl _ _ = {}
60-
61-
instance consRowSubset
62-
::
63-
( IsSymbol sym
64-
, Cons sym a subrowWithoutSym subrowWithSym
65-
, Cons sym a srcWithoutSym src
66-
, Lacks sym subrowWithoutSym
67-
, RowSubset src rl subrowWithoutSym
68-
) => RowSubset src (Cons sym a rl) subrowWithSym where
69-
subsetImpl _ src = insert (SProxy :: SProxy sym) (get (SProxy :: SProxy sym) src) (subsetImpl (RLProxy :: RLProxy rl) src)
70-
71-
subsetRow
72-
:: rl subR src
73-
. ListToRow rl subR
74-
=> RowToList subR rl
75-
=> RowSubset src rl subR
76-
=> {|src}
77-
-> RProxy subR
78-
-> {|subR}
79-
subsetRow src _ = subsetImpl (RLProxy :: RLProxy rl) src
80-
81-
select
82-
:: m rec rl subR
83-
. Monad m
84-
=> RowSubset rec rl subR
85-
=> RowToList subR rl
86-
=> ListToRow rl subR
87-
=> RProxy subR
88-
-> Query m {|rec} {|subR}
89-
select proxy = asks (map (flip subsetRow proxy))
90-
91-
rename
92-
:: m inter input output sym sym' a
93-
. Monad m
94-
=> IsSymbol sym
95-
=> IsSymbol sym'
96-
=> Cons sym a inter input
97-
=> Lacks sym inter
98-
=> Cons sym' a inter output
99-
=> Lacks sym' inter
100-
=> SProxy sym
101-
-> SProxy sym'
102-
-> Query m {|input} {|output}
103-
rename proxy proxy' = asks (map (R.rename proxy proxy'))
104-
105-
mutate
106-
:: m input output sym a
107-
. Monad m
108-
=> IsSymbol sym
109-
=> Lacks sym input
110-
=> Cons sym a input output
111-
=> SProxy sym
112-
-> ({|input} -> a)
113-
-> Query m {|input} {|output}
114-
mutate proxy f = asks (map (\r -> R.insert proxy (f r) r))
115-
116-
transmute
117-
:: m input sym a out
118-
. Monad m
119-
=> IsSymbol sym
120-
=> Lacks sym ()
121-
=> Cons sym a () out
122-
=> SProxy sym
123-
-> ({|input} -> a)
124-
-> Query m {|input} {|out}
125-
transmute proxy f = asks (map \r -> R.insert proxy (f r) {})
126-
12722
groupBy
12823
:: m a b
12924
. Monad m

src/Data/Query/Record.purs

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
module Data.Query.Record where
2+
3+
import Prelude
4+
5+
import Control.Monad.Reader.Class (asks)
6+
import Data.DataFrame (DataFrame(..))
7+
import Data.Function (on)
8+
import Data.List (sortBy)
9+
import Data.Newtype (over)
10+
import Data.Ordering (invert)
11+
import Data.Query (Query)
12+
import Data.Symbol (class IsSymbol, SProxy(..))
13+
import Prim.Row (class Cons, class Lacks)
14+
import Prim.RowList (class RowToList, Cons, Nil, kind RowList)
15+
import Record (get, insert)
16+
import Record (insert, rename) as R
17+
import Type.Row (class ListToRow, RLProxy(..), RProxy)
18+
19+
20+
arrange
21+
:: m sym a rec without
22+
. Ord a
23+
=> Monad m
24+
=> IsSymbol sym
25+
=> Lacks sym without
26+
=> Cons sym a without rec
27+
=> SProxy sym
28+
-> Boolean
29+
-> Query m ({|rec}) ({|rec})
30+
arrange proxy asc = asks (over DataFrame $ sortBy (comp `on` (get proxy)))
31+
where
32+
comp :: a -> a -> Ordering
33+
comp a = if asc then compare a else invert <<< compare a
34+
35+
pull
36+
:: m sym a rec without' without
37+
. Monad m
38+
=> IsSymbol sym
39+
=> Lacks sym without
40+
=> Lacks sym without'
41+
=> Cons sym a without rec
42+
=> SProxy sym
43+
-> Query m {|rec} a
44+
pull proxy = asks (over DataFrame $ map ( get proxy))
45+
46+
class RowSubset (row :: # Type) (xs :: RowList) (subrow :: # Type) | row xs -> subrow where
47+
subsetImpl :: RLProxy xs -> {|row} -> {|subrow}
48+
49+
instance nilRowSubset :: RowSubset row Nil () where subsetImpl _ _ = {}
50+
51+
instance consRowSubset
52+
::
53+
( IsSymbol sym
54+
, Cons sym a subrowWithoutSym subrowWithSym
55+
, Cons sym a srcWithoutSym src
56+
, Lacks sym subrowWithoutSym
57+
, RowSubset src rl subrowWithoutSym
58+
) => RowSubset src (Cons sym a rl) subrowWithSym where
59+
subsetImpl _ src = insert (SProxy :: SProxy sym) (get (SProxy :: SProxy sym) src) (subsetImpl (RLProxy :: RLProxy rl) src)
60+
61+
subsetRow
62+
:: rl subR src
63+
. ListToRow rl subR
64+
=> RowToList subR rl
65+
=> RowSubset src rl subR
66+
=> {|src}
67+
-> RProxy subR
68+
-> {|subR}
69+
subsetRow src _ = subsetImpl (RLProxy :: RLProxy rl) src
70+
71+
select
72+
:: m rec rl subR
73+
. Monad m
74+
=> RowSubset rec rl subR
75+
=> RowToList subR rl
76+
=> ListToRow rl subR
77+
=> RProxy subR
78+
-> Query m {|rec} {|subR}
79+
select proxy = asks (map (flip subsetRow proxy))
80+
81+
rename
82+
:: m inter input output sym sym' a
83+
. Monad m
84+
=> IsSymbol sym
85+
=> IsSymbol sym'
86+
=> Cons sym a inter input
87+
=> Lacks sym inter
88+
=> Cons sym' a inter output
89+
=> Lacks sym' inter
90+
=> SProxy sym
91+
-> SProxy sym'
92+
-> Query m {|input} {|output}
93+
rename proxy proxy' = asks (map (R.rename proxy proxy'))
94+
95+
mutate
96+
:: m input output sym a
97+
. Monad m
98+
=> IsSymbol sym
99+
=> Lacks sym input
100+
=> Cons sym a input output
101+
=> SProxy sym
102+
-> ({|input} -> a)
103+
-> Query m {|input} {|output}
104+
mutate proxy f = asks (map (\r -> R.insert proxy (f r) r))
105+
106+
transmute
107+
:: m input sym a out
108+
. Monad m
109+
=> IsSymbol sym
110+
=> Lacks sym ()
111+
=> Cons sym a () out
112+
=> SProxy sym
113+
-> ({|input} -> a)
114+
-> Query m {|input} {|out}
115+
transmute proxy f = asks (map \r -> R.insert proxy (f r) {})

src/Data/Query/Untyped.purs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module Data.Query.Untyped where
2+
3+
import Prelude
4+
5+
import Control.Monad.Reader.Trans (asks)
6+
import Data.Bifunctor (lmap)
7+
import Data.DataFrame (DataFrame(..))
8+
import Data.Foldable (elem)
9+
import Data.Function (on)
10+
import Data.List (sortBy)
11+
import Data.List.NonEmpty (NonEmptyList)
12+
import Data.Map (Map)
13+
import Data.Map (filterKeys, insert, lookup, pop) as Map
14+
import Data.Maybe (Maybe, fromMaybe, maybe)
15+
import Data.Newtype (over)
16+
import Data.Ordering (invert)
17+
import Data.Query (Query)
18+
import Data.String (Pattern(..))
19+
import Data.String.NonEmpty (NonEmptyString, stripPrefix)
20+
import Data.Tuple (uncurry)
21+
import Types (Column, Row)
22+
23+
arrange
24+
:: m a
25+
. Ord a
26+
=> Monad m
27+
=> Column
28+
-> Query m (Row a) (Row a)
29+
arrange column = asks (over DataFrame (sortBy (comp `on` Map.lookup columnName)))
30+
where
31+
withoutMinusPrefix = stripPrefix (Pattern "-") column
32+
columnName = fromMaybe column withoutMinusPrefix
33+
asc = maybe true (const false) withoutMinusPrefix
34+
comp a = if asc then compare a else invert <<< compare a
35+
36+
pull
37+
:: m a
38+
. Monad m
39+
=> Column
40+
-> Query m (Row a) (Maybe a)
41+
pull column = asks (map (Map.lookup column))
42+
43+
select
44+
:: m a
45+
. Monad m
46+
=> NonEmptyList Column
47+
-> Query m (Row a) (Row a)
48+
select ks = asks (map (Map.filterKeys (flip elem ks)))
49+
50+
rename
51+
:: m a
52+
. Monad m
53+
=> Column
54+
-> Column
55+
-> Query m (Row a) (Row a)
56+
rename from to = transmute from to identity
57+
58+
mutate
59+
:: m a
60+
. Monad m
61+
=> Column
62+
-> (Row a -> a)
63+
-> Query m (Row a) (Row a)
64+
mutate column f = asks (map (\r -> Map.insert column (f r) r))
65+
66+
transmute
67+
:: m a
68+
. Monad m
69+
=> Column
70+
-> Column
71+
-> (a -> a)
72+
-> Query m (Row a) (Row a)
73+
transmute from to f = asks (map go)
74+
where
75+
go row =
76+
maybe
77+
row
78+
(lmap f >>> uncurry (Map.insert to))
79+
(Map.pop from row)

src/Main.purs

-9
This file was deleted.

0 commit comments

Comments
 (0)