我有一个Either
newtype Answer a = Answer (Either Text a)
可以转换为JSON:
instance ToJSON a => ToJSON (Answer a) where
toJSON (Answer (Left msg)) = object
[ "error" .= True
, "message" .= msg
, "data" .= Null
]
toJSON (Answer (Right val)) = object
[ "error" .= False
, "message" .= pack "OK"
, "data" .= val
]
答案有两种:
errorAnswer :: Text -> Answer a
errorAnswer = Answer . Left
valueAnswer :: a -> Answer a
valueAnswer = Answer . Right
我在Handler
monad中运行了一组函数并返回Answer
。
有些功能测试了一些东西:
checkSomething :: Handler (Answer a) -> Handler (Answer a)
checkSomething action = do
if sometingIsWrong
then pure (errorAnswer "Something was wrong")
else action
其他功能操纵TVar
中的App
变量:
readSomething
:: (App -> TVar a) -> (a -> Either Text b) -> Handler (Answer a)
readSomething var f =
readVar var >>= pure . Answer . f
where
readVar var = getYesod >>= liftIO . readTVarIO . var
上面这两个函数很容易构成:
handleRequest :: ToJSON a => Handler (Answer a)
handleRequest =
checkSomething $ readSomething someVar someProjection
但是当我有更多支票checkSomething
时,它会变得很难。另外,我想将returnJson
放在某处,最后返回Value
。
有没有办法在Either
样式中编写处理程序(同样,Maybe
喜欢)?例如:
handleRequest :: Handler (Answer Int)
handleRequest = do
checkSomething0 -- Do not continue if (Answer (Left _))
checkSomething1 -- Do not continue if (Answer (Left _))
doSomething -- Everything above was fine
一个想法是将Alternative
实例添加到Handler (Answer a)
,但这是一个问题:
empty = Answer (Left ???)
我在这里丢失了一条消息,如果发生错误,服务器应该返回。