不确定如何为Aeson对分配monadic值

时间:2016-02-04 12:44:44

标签: haskell aeson

请考虑以下代码:

    S.get "/budget/:bid/month/:mnth" $ do
      mbid <- param "bid"
      (budget :: Maybe Budget) <- liftIO $ getBudget $ toSqlKey mbid
      (categories :: [Entity Category]) <- liftIO $ getCategories $ toSqlKey mbid
      case budget of 
        Nothing -> json $ object [ "message" .= ("No budget was found!" :: String) ]
        Just b -> do
          json $ object [
              "categoryExpenditures" .= map (\x -> object ["spent" .= liftIO $ 
                calculateCategoryBalanceForMonth (entityKey x) 1 >>= (\y -> y) ]) categories
            ]

到目前为止,calculateCategoryBalanceForMonth的类型为calculateCategoryBalanceForMonth :: CategoryId -> Int -> IO Double

我正在尝试映射categories并在Aeson中返回categoryExpenditures列表作为JSON对象。但是,我无法弄清楚如何将值从liftIO返回给.=运算符。

我的尝试涉及将赋值运算符移至>>= (\y -> y)>>= id,我希望id返回Double,或者至少有ToJSON实例的东西。但情况似乎并非如此。

我也知道使用liftIO表达式的赋值运算符,然后将赋值的变量传递给.=运算符,但我不确定如何在匿名函数中使用赋值运算符对于地图。

我可能做错了什么?需要更清晰吗?

1 个答案:

答案 0 :(得分:2)

我假设您正在使用底部为IO的monad堆栈。

object[Pair]为参数,但您尝试将IO传递给(>>=)(>>= id)内的保留在 monad中(根据定义!),因此(>>= id)不会按照您的意愿执行(事实上,Monad m => m (m a) -> m a的签名是join,ergo Just b -> do expenditures <- forM categories (\x -> do spent <- liftIO $ calculateCategoryBalanceForMonth (entityKey x) 1 return $ object [ "spent" .= spent ]) json $ object [ "categoryExpenditures" .= expenditures ] )。你想稍微改变一下:

mapM

要使用monadic结果进行映射,请使用forMforM = flip mapMrequired)。