-
Notifications
You must be signed in to change notification settings - Fork 0
/
CSV.idr
128 lines (109 loc) · 3.31 KB
/
CSV.idr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
module CSV
import Effects
import Effect.File
import Effect.StdIO
import Effect.Exception
import Providers
import public Parser
%access public
%default total
data CSVError = NoSuchFile
| ColumnMismatch
| RowMismatch
instance Show CSVError where
show NoSuchFile = "NoSuchFile"
show ColumnMismatch = "ColumnMismatch"
namespace Schema
data Schema : Type where
Nil : Schema
(::) : String -> Schema -> Schema
length : Schema -> Nat
length [] = 0
length (x :: xs) = 1 + length xs
private
toSchema : (format : Format) -> Schema
toSchema (c :: k) = c :: toSchema k
toSchema [] = []
data IsElem : String -> Schema -> Type where
Here : IsElem x (x :: xs)
There : IsElem x xs -> IsElem x (y :: xs)
namespace Row
data Row : Schema -> Type where
Nil : Row []
(::) : (s : (String, String))
-> Row schema
-> Row (fst s :: schema)
namespace CSV
data CSV : Schema -> Nat -> Type where
Nil : CSV schema 0
(::) : Row schema -> CSV schema n -> CSV schema (S n)
lookup : (f : String)
-> Row schema
-> {default tactics {search 100;} p : IsElem f schema}
-> String
lookup (fst s) (s :: x) {p=Here} = snd s
lookup f (s :: x) {p=There p'} = lookup f x
lookup f [] {p=Here} impossible
index : Fin n -> CSV schema n -> Row schema
index FZ (row :: _) = row
index (FS i) (_ :: rows) = index i rows
readHeader : (filename : String)
-> { [FILE_IO ()] } Eff String
readHeader filename =
case !(open filename Read) of
False => return ""
True => do
header <- [| trim readLine |]
close
pure header
readSchema : (filename : String)
-> { [FILE_IO (), STDIO] } Eff (Provider Schema)
readSchema filename = do
header <- readHeader filename
{-let parsed = parse header-}
let parsed = Right $ split (== ',') header
case parsed of
Left error => do
pure $ Error "error"
Right format => do
let schema = toSchema format
pure $ Provide schema
fromVect : {schema : Schema}
-> (vals : Vect (length schema) String)
-> Row schema
fromVect {schema=[]} [] = []
fromVect {schema=(x :: xs)} (y :: ys) = (x, y) :: (fromVect {schema=xs} ys)
private
processRow : (f : Format)
-> (schema : Schema)
-> { [EXCEPTION CSVError] } Eff (Row schema)
processRow (_ :: _) [] = raise ColumnMismatch
processRow [] (_ :: _) = raise ColumnMismatch
processRow (t :: k) (f :: fs) = pure $ (f, t) :: !(processRow k fs)
processRow [] [] = pure []
partial
readRows : (n : Nat)
-> (schema : Schema)
-> { [FILE_IO (OpenFile Read), EXCEPTION CSVError] } Eff (CSV schema n)
readRows Z _ = pure []
readRows (S n) schema =
if !eof
then raise RowMismatch
else do
row <- readLine
if row /= ""
then pure $ !(processRow (parse' row) schema) :: !(readRows n schema)
else raise RowMismatch
partial
readCSV : {schema : Schema}
-> String
-> (n : Nat)
-> { [FILE_IO (), EXCEPTION CSVError] } Eff (CSV schema n)
readCSV {schema} file n =
case !(open file Read) of
True => do
_ <- readLine
rows <- readRows n schema
close
pure rows
False => raise NoSuchFile