-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReaderQ.hs
129 lines (107 loc) · 5.34 KB
/
ReaderQ.hs
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
129
module ReaderQ where
import Data.List
import Data.Bits
import Data.Char
import Data.List.Split
import qualified Data.Map as M
import Debug.Trace
import ErrorMsg
--
splitBySeparator :: String -> String -> [String]
splitBySeparator sep s =
if last s == last sep then endBy sep s else splitOn sep s
-- read the DB line by line -- no speacial parsing, assume that the delimiters are whitespaces
readInput :: String -> IO String
readInput path = do
content <- readFile path
return content
readEither :: (Read a) => String -> Either a String
readEither s = case reads s of
[(x, "")] -> Left x
_ -> Right s
readErr :: (Read a) => String -> String -> a
readErr varType s = case reads s of
[(x, "")] -> x
_ -> error $ error_tableTypeError s varType
--readEithers :: String -> Either Bool (Either Int (Either Double String))
--readEithers s = case (reads s) :: [(Bool,String)] of
-- [(x, "")] -> Left x
-- _ -> case (reads s) :: [(Int,String)] of
-- [(x, "")] -> Right (Left x)
-- _ -> case (reads s) :: [(Double,String)] of
-- [(x, "")] -> Right (Right (Left x))
-- _ -> Right (Right (Right s))
-- tostring function
intToString s = do
let x = read s :: Double
return x
-- djb2 hash
hash :: String -> Double
hash = fromIntegral . foldl' (\h c -> xor (33*h) (ord c)) 5381
-- tries to read an integer, then a boolean, and if fails, returns the hash of the input string
readIntBoolString :: String -> Double
readIntBoolString s =
let a = readEither s :: Either Double String in
case a of
Left x -> x
Right x ->
let b = readEither s :: Either Bool String in
case b of
Left x -> fromIntegral $ fromEnum x
Right x -> hash s
readDoubles :: String -> String -> [[Double]]
readDoubles s separator = fmap (map readIntBoolString . (splitBySeparator separator)) (lines s)
-- read the database from the file as a matrix of doubles
-- read is as a single table row
readDB :: String -> String -> IO ([String], [[Double]])
readDB dbFileName separator = do
(firstLine:ls) <- fmap lines (readInput dbFileName)
let varNames = splitBySeparator separator firstLine
let table = readDoubles (foldr (\x y -> x ++ "\n" ++ y) "" ls) separator
return (varNames, table)
-- read the database from the file as several matrices of different data types
readDBDifferentTypes :: String -> String -> String -> M.Map String (M.Map String String) -> IO ([String], [[Bool]], [[Int]], [[Double]], [[String]], [Int], [Int], [Int], [Int])
readDBDifferentTypes dbFileName separator tableName typeMap = do
(varNames, table) <- readDBString dbFileName separator
let varTypes = map (\x -> typeMap ! tableName ! x) varNames
let filtBool = map (\s -> map toLower (take 4 s) == "bool") varTypes
let filtInt = map (\s -> map toLower (take 3 s) == "int" || map toLower (take 6 s) == "bigint") varTypes
let filtDouble = map (\s -> map toLower (take 5 s) == "float") varTypes
let filtString = map (\s -> map toLower (take 4 s) == "text") varTypes
let boolCols = fmap (map (readErr "bool") . (filterByKey filtBool)) table :: [[Bool]]
let intCols = fmap (map (readErr "int") . (filterByKey filtInt)) table :: [[Int]]
let dblCols = fmap (map (readErr "float") . (filterByKey filtDouble)) table :: [[Double]]
let strCols = fmap (filterByKey filtString) table :: [[String]]
let indices = [0..length varNames - 1]
let boolIndices = (filterByKey filtBool) indices
let intIndices = (filterByKey filtInt) indices
let dblIndices = (filterByKey filtDouble) indices
let stringIndices = (filterByKey filtString) indices
return (varNames, boolCols, intCols, dblCols, strCols, boolIndices, intIndices, dblIndices, stringIndices)
--readDifferentTypes :: [String] -> String -> String -> [[Either Bool (Either Int (Either Double String))]]
--readDifferentTypes varTypes s separator =
-- fmap (\xs -> zipWith readSomeType varTypes (splitBySeparator separator xs)) (lines s)
--readSomeType :: String -> String -> Either Bool (Either Int (Either Double String))
--readSomeType varType s =
-- let a1 = readEither s :: Either Bool String in
-- case a1 of
-- Left x -> if varType == "bool" then Left x else error $ error_tableTypeError x varType
-- _ -> let a2 = readEither s :: Either Int String in
-- case a2 of
-- Left x -> if varType == "int" then Right (Left x) else error $ error_tableTypeError x varType
-- _ -> let a3 = readEither s :: Either Double String in
-- case a3 of
-- Left x -> if varType == "float" then Right (Right (Left x)) else error $ error_tableTypeError x varType
-- _ -> Right (Right (Right s))
-- read the database from the file as a matrix of strings
-- read is as a single table row
readDBString :: String -> String -> IO ([String], [[String]])
readDBString dbFileName separator = do
(firstLine:ls) <- fmap lines (readInput dbFileName)
let varNames = splitBySeparator separator firstLine
let table = map (splitBySeparator separator) ls
return (varNames, table)
filterByKey :: [Bool] -> [b] -> [b]
filterByKey keys vals =
let fs = filter (\(x,y) -> x) (zip keys vals) in
map snd fs