【问题标题】:Unexpected return type of Acid State query (Happstack)酸状态查询的意外返回类型(Happstack)
【发布时间】:2013-01-04 05:01:36
【问题描述】:

我正在尝试用一些额外的功能扩展Happstack crash course 博客:在主页上显示所有标签的列表。

我的博客记录是这样的:

data Blog = Blog
    { nextPostId :: PostId
    , posts      :: IxSet Post
    , allTags    :: [Text] 
    }
    deriving (Data, Typeable)

我通过以下方式通过 id 获取博客文章(从速成课程中复制粘贴):

-- Models.hs

postById :: PostId -> Query Blog (Maybe Post)
postById pid =
     do Blog{..} <- ask
        return $ getOne $ posts @= pid

-- Controller.hs

viewPage :: AcidState Blog -> ServerPart Response
viewPage acid = 
     do pid <- PostId <$> lookRead "id"
        mPost <- query' acid (PostById pid)
        ...
        -- mPost has type Maybe Post here
        ...

而且它工作正常。

当我尝试以类似方式查询所有标签时:

-- Models.hs 

getTags :: Query Blog [Text]
getTags = 
    do Blog{..} <- ask
       return allTags

-- Controller.hs

serveTags :: AcidState Blog -> [Text]
serveTags acid = query' acid GetTags

这行不通。错误堆栈跟踪是:

Blog/Controllers.hs:154:18:
   Couldn't match type `[Text]' with `Text'
   Expected type: [Text]
   Actual type: [acid-state-0.8.1:Data.Acid.Common.EventResult
                                       GetTags]
   In the return type of a call of query'
   In the expression: query' acid GetTags

我不明白为什么query' 的返回类型是[EventResult GetTags],而它应该是[Text]

这个错误的原因是什么?有办法解决吗?

【问题讨论】:

  • 该错误消息向我表明EventResult 是一个类型函数,而EventResult GetTags[Text],而您假设它应该是Text
  • 类型错误中提到包名的事实令人担忧。我怀疑以某种方式涉及多种版本的酸态。检查你的包数据库的完整性,包括关于你的编译过程的更多细节(你在使用 Cabal 吗?你提供了什么参数?)
  • 只是想把它留在这里:感谢改进酸状态教程!

标签: haskell happstack acid-state


【解决方案1】:

问题是你在serveTags 函数上的类型签名,它应该是一元的:

serveTags :: MonadIO m => AcidState Blog -> m [Text]
serveTags acid = query' acid GetTags

EventResult 是一个类型族,在这里解析为[Text]。由于query' 是单子,因此您的类型签名已解析为列表单子,即m Text,其中m 是列表单子,因此会出现令人困惑的错误消息。

【讨论】:

  • 谢谢!但是如果我需要得到[Text],应该怎么做呢?
  • 只需使用 do 表示法即可获得实际值,即tags &lt;- serveTags acid
  • 不幸的是,我对此有疑问:当我尝试执行以下操作时:arrangeTags :: AcidState Blog -&gt; [Text] arrangeTags acid = do t &lt;- serveTags acid return t 我收到了No instance for (MonadIO []) arising from a use of 'serveTags' 消息。
  • 你无法在 Haskell 中转义 IO。 do x &lt;- y; return xy 相同,所以你的arrangeTags 只是serveTags 的别名。它必须具有相同的类型,并且必须涉及MonadIO m =&gt; m ...。请注意,Happstack 中的 ServerPart 实际上是 MonadIO 的一个实例,因此您可以直接在 Happstack 处理程序中使用带有 do-notation 的 serveTags,就像在速成课程示例中使用的 query' acid (PostById pid) 一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多