If I have an array ["addTask", {"id": "1", "description": "d", "dependsOn": [], "dependentTasks": []}]
.
data Task = Task
{ id :: String
, description :: String
, dependsOn :: [String]
, dependentTasks :: [String]
} deriving (Eq, Show, Generic, ToJSON, FromJSON)
type Change = Storage -> Storage
addTask :: Task -> Change
addTask (Task id desc dep dept) = insert id (Task id desc dep dept)
How can I create a parser that would produce a addTask from that?
instance FromJSON (Storage -> Storage) where
parseJSON (Array v) = do
name <- parseJSON $ v V.! 0 :: Just String
task <- parseJSON $ v V.! 1 :: Just Task
return (addTask task)
This is my current attempt which doesn't work.
I would go on and parse the Array into a Tuple (String,Task)
and then use simple pattern matching, you might need to specify the type of "addTask" if you are using OverloadedStrings
, which can be done with ScopedTypeVariables
(just add it to the left hand side of the .. :: (String, Task) <- parse..
).
instance FromJSON (Storage -> Storage) where
parseJSON v = do ("addTask",t) <- parseJSON v
return $ addTask t
Note: I did not compile or test this code
Edit
Using alternative is really easy you just define two parsers and combine them
instance FromJSON (Storage -> Storage) where
parseJSON v = let addP = do ("addTask",t) <- parseJSON v
return $ addTask t
rmP = do ("rmTask",n) <- parseJSON v
return $ rmTask n
in addP <|> rmP
I am assuming that rmTask :: Int -> Change
otherwise cou can always case
on the first element of the tuple.