1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
4 ( Decoder, Error(..), decode, parse
5 , text, bool, int, float
9 , map, map2, succeed, fail, andThen, oneOf
14import Data.Text (Text)
15import Prelude hiding (fail, map, maybe)
17import qualified Control.Monad as Monad
18import qualified Data.Aeson as Aeson
19import qualified Data.ByteString.Lazy as BS
20import qualified Data.HashMap.Lazy as HashMap
21import qualified Data.Scientific as Scientific
22import qualified Data.Text as Text
23import qualified Data.Vector as Vector
24import Data.Vector ((!?))
33 { _run :: (Error -> Error) -> Aeson.Value -> Either Error a
41 | Failure Aeson.Value String
44decode :: Decoder a -> Aeson.Value -> Either Error a
49parse :: Decoder a -> BS.ByteString -> Either (Maybe Error) a
50parse decoder bytestring =
51 case Aeson.eitherDecode bytestring of
56 case decode decoder json of
70 Decoder $ \mkError value ->
76 Left (mkError (Failure value "a string"))
81 Decoder $ \mkError value ->
87 Left (mkError (Failure value "a boolean"))
92 Decoder $ \mkError value ->
94 Aeson.Number number ->
95 case Scientific.toBoundedInteger number of
97 Left (mkError (Failure value "an integer"))
103 Left (mkError (Failure value "an integer"))
106float :: Decoder Float
108 Decoder $ \mkError value ->
110 Aeson.Number number ->
111 Right (Scientific.toRealFloat number)
114 Left (mkError (Failure value "a float"))
121list :: Decoder a -> Decoder [a]
123 Decoder $ \mkError value ->
125 Aeson.Array vector ->
127 Vector.imapM (\i v -> run (mkError . Index i) v) vector
130 Left (mkError (Failure value "an array"))
133dict :: Decoder a -> Decoder (HashMap.HashMap Text a)
135 Decoder $ \mkError value ->
137 Aeson.Object hashMap ->
138 HashMap.traverseWithKey (\k v -> run (mkError . Field k) v) hashMap
141 Left (mkError (Failure value "an object"))
144maybe :: Decoder a -> Decoder (Maybe a)
146 Decoder $ \mkError value ->
147 case run mkError value of
159field :: Text -> Decoder a -> Decoder a
160field name (Decoder run) =
161 Decoder $ \mkError value ->
163 Aeson.Object hashMap ->
164 case HashMap.lookup name hashMap of
166 run (mkError . Field name) v
170 Failure value ("a \"" ++ Text.unpack name ++ "\" field")
173 Left (mkError (Failure value "an object"))
176at :: [Text] -> Decoder a -> Decoder a
178 foldr field decoder names
185index :: Int -> Decoder a -> Decoder a
186index i (Decoder run) =
187 Decoder $ \mkError value ->
189 Aeson.Array vector ->
192 run (mkError . Index i) v
196 Failure value ("index " ++ show i ++ " of an array")
199 Left (mkError (Failure value "an array"))
206map :: (a -> value) -> Decoder a -> Decoder value
207map func (Decoder run) =
208 Decoder $ \mkError value ->
209 func <$> run mkError value
212map2 :: (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value
213map2 func (Decoder runA) (Decoder runB) =
214 Decoder $ \mkError value ->
216 <$> runA mkError value
217 <*> runB mkError value
220apply :: Decoder (a -> b) -> Decoder a -> Decoder b
221apply (Decoder runFunc) (Decoder runArg) =
222 Decoder $ \mkError value ->
223 do func <- runFunc mkError value
224 arg <- runArg mkError value
228instance Functor Decoder where
233instance Applicative Decoder where
241instance Monad Decoder where
245 (>>=) decoder callback =
246 andThen callback decoder
256succeed :: a -> Decoder a
258 Decoder $ \_ _ -> Right a
261fail :: String -> Decoder a
263 Decoder $ \mkError value ->
264 Left (mkError (Failure value msg))
267andThen :: (a -> Decoder b) -> Decoder a -> Decoder b
268andThen callback (Decoder runA) =
269 Decoder $ \mkError value ->
270 do a <- runA mkError value
271 let (Decoder runB) = callback a
279oneOf :: [Decoder a] -> Decoder a
281 Decoder (oneOfHelp decoders [])
284oneOfHelp :: [Decoder a] -> [Error] -> (Error -> Error) -> Aeson.Value -> Either Error a
285oneOfHelp decoders errors mkError value =
288 Left (mkError (OneOf (reverse errors)))
290 Decoder run : otherDecoders ->
291 case run mkError value of
296 oneOfHelp otherDecoders (err:errors) mkError value
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list