Added basic FromAdnot class as well
Getty Ritter
7 years ago
7 | 7 | {-# LANGUAGE ScopedTypeVariables #-} |
8 | 8 | {-# LANGUAGE DefaultSignatures #-} |
9 | 9 | {-# LANGUAGE DataKinds #-} |
10 | {-# LANGUAGE GADTs #-} | |
10 | 11 | |
11 | 12 | module Data.Adnot.Class where |
12 | 13 | |
14 | import Control.Monad ((>=>)) | |
15 | import Data.Adnot.Parse | |
13 | 16 | import Data.Adnot.Type |
14 | 17 | import Data.Adnot.Emit |
15 | 18 | import Data.Int |
16 | 19 | import Data.Word |
20 | import qualified Data.ByteString as BS | |
17 | 21 | import qualified Data.ByteString.Lazy as BSL |
18 | 22 | import qualified Data.Foldable as F |
19 | 23 | import qualified Data.List.NonEmpty as NE |
97 | 101 | default toAdnot :: (Generic a, GenToAdnot (Rep a)) => a -> Value |
98 | 102 | toAdnot = genericToAdnot |
99 | 103 | |
100 |
-- |
|
104 | -- Integral types | |
101 | 105 | instance ToAdnot Int where |
102 | 106 | toAdnot n = Integer (fromIntegral n) |
103 | 107 | |
131 | 135 | instance ToAdnot Word64 where |
132 | 136 | toAdnot n = Integer (fromIntegral n) |
133 | 137 | |
134 |
-- |
|
138 | -- Rational/Floating types | |
135 | 139 | instance ToAdnot Double where |
136 | 140 | toAdnot d = Double d |
137 | 141 | |
138 | 142 | instance ToAdnot Float where |
139 | 143 | toAdnot d = Double (fromRational (toRational d)) |
140 | 144 | |
141 |
-- |
|
145 | -- String types | |
142 | 146 | instance {-# INCOHERENT #-} ToAdnot String where |
143 | 147 | toAdnot s = String (T.pack s) |
144 | 148 | |
151 | 155 | instance ToAdnot Char where |
152 | 156 | toAdnot c = String (T.singleton c) |
153 | 157 | |
154 |
-- |
|
158 | -- List types | |
155 | 159 | instance ToAdnot a => ToAdnot [a] where |
156 | 160 | toAdnot ls = List (fmap toAdnot (V.fromList ls)) |
157 | 161 | |
164 | 168 | instance ToAdnot a => ToAdnot (NE.NonEmpty a) where |
165 | 169 | toAdnot ls = List (V.fromList (F.toList (fmap toAdnot ls))) |
166 | 170 | |
167 |
-- |
|
171 | -- Mapping types | |
168 | 172 | instance ToAdnot a => ToAdnot (MS.Map T.Text a) where |
169 | 173 | toAdnot ls = Product (fmap toAdnot ls) |
170 | 174 | |
171 |
-- |
|
175 | -- Tuples | |
172 | 176 | instance ToAdnot () where |
173 | 177 | toAdnot () = List [] |
174 | 178 | |
182 | 186 | => ToAdnot (a, b, c, d) where |
183 | 187 | toAdnot (a, b, c, d) = List [toAdnot a, toAdnot b, toAdnot c, toAdnot d] |
184 | 188 | |
185 |
-- |
|
189 | -- Common Haskell algebraic data types | |
186 | 190 | instance ToAdnot a => ToAdnot (Maybe a) where |
187 | 191 | toAdnot Nothing = Sum "Nothing" [] |
188 | 192 | toAdnot (Just x) = Sum "Just" [toAdnot x] |
195 | 199 | toAdnot True = Symbol "True" |
196 | 200 | toAdnot False = Symbol "False" |
197 | 201 | |
198 |
-- |
|
202 | -- Parsing | |
203 | ||
204 | decode :: FromAdnot a => BS.ByteString -> Either String a | |
205 | decode = decodeValue >=> parseAdnot | |
199 | 206 | |
200 | 207 | type ParseError = String |
201 | 208 | type Parser a = Either ParseError a |
205 | 212 | Sum t as -> k t as |
206 | 213 | _ -> Left ("Expected sum in " ++ n) |
207 | 214 | |
215 | withProduct :: String -> (Product -> Parser a) -> Value -> Parser a | |
216 | withProduct n k val = case val of | |
217 | Product ps -> k ps | |
218 | _ -> Left ("Expected product in " ++ n) | |
219 | ||
220 | withList :: String -> (Array -> Parser a) -> Value -> Parser a | |
221 | withList n k val = case val of | |
222 | List ls -> k ls | |
223 | _ -> Left ("Expected list in " ++ n) | |
224 | ||
225 | withInteger :: String -> (Integer -> Parser a) -> Value -> Parser a | |
226 | withInteger n k val = case val of | |
227 | Integer i -> k i | |
228 | _ -> Left ("Expected integer in " ++ n) | |
229 | ||
230 | withDouble :: String -> (Double -> Parser a) -> Value -> Parser a | |
231 | withDouble n k val = case val of | |
232 | Double d -> k d | |
233 | _ -> Left ("Expected double in " ++ n) | |
234 | ||
235 | withSymbol :: String -> (T.Text -> Parser a) -> Value -> Parser a | |
236 | withSymbol n k val = case val of | |
237 | Symbol s -> k s | |
238 | _ -> Left ("Expected symbol in " ++ n) | |
239 | ||
240 | withString :: String -> (T.Text -> Parser a) -> Value -> Parser a | |
241 | withString n k val = case val of | |
242 | String s -> k s | |
243 | _ -> Left ("Expected string in " ++ n) | |
244 | ||
208 | 245 | class FromAdnot a where |
209 | 246 | parseAdnot :: Value -> Parser a |
247 | ||
248 | instance FromAdnot Value where | |
249 | parseAdnot = return | |
250 | ||
251 | -- Integer Types | |
252 | instance FromAdnot Int where | |
253 | parseAdnot = withInteger "Int" (return . fromIntegral) | |
254 | ||
255 | instance FromAdnot Integer where | |
256 | parseAdnot = withInteger "Int" return | |
257 | ||
258 | instance FromAdnot Int8 where | |
259 | parseAdnot = withInteger "Int8" (return . fromIntegral) | |
260 | ||
261 | instance FromAdnot Int16 where | |
262 | parseAdnot = withInteger "Int16" (return . fromIntegral) | |
263 | ||
264 | instance FromAdnot Int32 where | |
265 | parseAdnot = withInteger "Int32" (return . fromIntegral) | |
266 | ||
267 | instance FromAdnot Int64 where | |
268 | parseAdnot = withInteger "Int64" (return . fromIntegral) | |
269 | ||
270 | instance FromAdnot Word where | |
271 | parseAdnot = withInteger "Word" (return . fromIntegral) | |
272 | ||
273 | instance FromAdnot Word8 where | |
274 | parseAdnot = withInteger "Word8" (return . fromIntegral) | |
275 | ||
276 | instance FromAdnot Word16 where | |
277 | parseAdnot = withInteger "Word16" (return . fromIntegral) | |
278 | ||
279 | instance FromAdnot Word32 where | |
280 | parseAdnot = withInteger "Word32" (return . fromIntegral) | |
281 | ||
282 | instance FromAdnot Word64 where | |
283 | parseAdnot = withInteger "Word64" (return . fromIntegral) | |
284 | ||
285 | -- Rational/Floating types | |
286 | ||
287 | instance FromAdnot Double where | |
288 | parseAdnot = withDouble "Double" return | |
289 | ||
290 | instance FromAdnot Float where | |
291 | parseAdnot = | |
292 | withDouble "Float" (return . fromRational . toRational) | |
293 | ||
294 | -- String types | |
295 | ||
296 | instance {-# INCOHERENT #-} FromAdnot String where | |
297 | parseAdnot = withString "String" (return . T.unpack) | |
298 | ||
299 | instance FromAdnot T.Text where | |
300 | parseAdnot = withString "Text" return | |
301 | ||
302 | instance FromAdnot TL.Text where | |
303 | parseAdnot = withString "Text" (return . TL.fromStrict) | |
304 | ||
305 | instance FromAdnot Char where | |
306 | parseAdnot = withString "Char" $ \s -> case T.uncons s of | |
307 | Just (c, "") -> return c | |
308 | _ -> Left "Expected a single-element string" | |
309 | ||
310 | ||
311 | -- List types | |
312 | instance FromAdnot a => FromAdnot [a] where | |
313 | parseAdnot = withList "List" $ \ls -> | |
314 | F.toList <$> mapM parseAdnot ls | |
315 | ||
316 | instance FromAdnot a => FromAdnot (V.Vector a) where | |
317 | parseAdnot = withList "Vector" $ \ls -> | |
318 | mapM parseAdnot ls | |
319 | ||
320 | instance FromAdnot a => FromAdnot (Seq.Seq a) where | |
321 | parseAdnot = withList "Seq" $ \ls -> | |
322 | Seq.fromList . F.toList <$> mapM parseAdnot ls | |
323 | ||
324 | instance FromAdnot a => FromAdnot (NE.NonEmpty a) where | |
325 | parseAdnot = withList "NonEmpty" $ \ls -> do | |
326 | lst <- mapM parseAdnot ls | |
327 | case F.toList lst of | |
328 | [] -> Left "Expected non-empty sequence" | |
329 | (x:xs) -> Right (x NE.:| xs) | |
330 | ||
331 | -- Mapping types | |
332 | instance FromAdnot a => FromAdnot (MS.Map T.Text a) where | |
333 | parseAdnot = withProduct "Map" $ \ms -> do | |
334 | lst <- mapM parseAdnot ms | |
335 | return (MS.fromList (F.toList lst)) | |
336 | ||
337 | -- Tuples | |
338 | instance FromAdnot () where | |
339 | parseAdnot = withList "()" $ \ls -> | |
340 | case ls of | |
341 | [] -> return () | |
342 | _ -> Left "Expected empty list" | |
343 | ||
344 | instance (FromAdnot a, FromAdnot b) => FromAdnot (a, b) where | |
345 | parseAdnot = withList "(a, b)" $ \ls -> | |
346 | case ls of | |
347 | [a, b] -> (,) <$> parseAdnot a <*> parseAdnot b | |
348 | _ -> Left "Expected two-element list" | |
349 | ||
350 | ||
351 | instance (FromAdnot a, FromAdnot b, FromAdnot c) => FromAdnot (a, b, c) where | |
352 | parseAdnot = withList "(a, b, c)" $ \ls -> | |
353 | case ls of | |
354 | [a, b, c] -> (,,) <$> parseAdnot a <*> parseAdnot b <*> parseAdnot c | |
355 | _ -> Left "Expected three-element list" | |
356 | ||
357 | ||
358 | instance (FromAdnot a, FromAdnot b, FromAdnot c, FromAdnot d) | |
359 | => FromAdnot (a, b, c, d) where | |
360 | parseAdnot = withList "(a, b, c, d)" $ \ls -> | |
361 | case ls of | |
362 | [a, b, c, d] -> (,,,) <$> parseAdnot a <*> parseAdnot b | |
363 | <*> parseAdnot c <*> parseAdnot d | |
364 | _ -> Left "Expected four-element list" | |
365 | ||
366 | -- Common Haskell algebraic data types | |
367 | instance FromAdnot a => FromAdnot (Maybe a) where | |
368 | parseAdnot = withSum "Maybe" go | |
369 | where go "Nothing" [] = return Nothing | |
370 | go "Just" [x] = Just <$> parseAdnot x | |
371 | go _ _ = Left "Invalid Maybe" | |
372 | ||
373 | instance (FromAdnot a, FromAdnot b) => FromAdnot (Either a b) where | |
374 | parseAdnot = withSum "Either" go | |
375 | where go "Left" [x] = Left <$> parseAdnot x | |
376 | go "Right" [x] = Right <$> parseAdnot x | |
377 | go _ _ = Left "Invalid Either" | |
378 | ||
379 | instance FromAdnot Bool where | |
380 | parseAdnot = withSymbol "Bool" go | |
381 | where go "True" = return True | |
382 | go "False" = return False | |
383 | go _ = Left "Invalid Bool" |