Monad 在从 Lift 移植到 Yesod 的 Persistent 时遇到了麻烦
Posted
技术标签:
【中文标题】Monad 在从 Lift 移植到 Yesod 的 Persistent 时遇到了麻烦【英文标题】:Monad troubles porting from Lift to Yesod's Persistent 【发布时间】:2012-09-27 18:57:51 【问题描述】:我有一个 Lift 应用程序,我将其移植到 Yesod,作为学习框架和 Haskell 的一种方式。应用程序的一部分仅驻留在 TCP 和数据库层:解析来自套接字连接的传入字节并将它们转换为更新以供模型处理。我在 Scala 中使用正则表达式和模式匹配进行了此操作,但未能在 Haskell 中重现它。
一个高度简化的例子:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
Person
name String
deriving Show
UnknownMessage
text String
deriving Show
|]
parseMsg m = runDB $ do
case ms of
["add",name] -> insert PersonpersonName = name
["delete",name] -> deleteWhere [PersonName ==. name]
["change",from,to] -> updateWhere [PersonName ==. from] [PersonName =.to]
_ -> insert UnknownMessageunknownMessageText = m
where
ms = splitRegex (mkRegex ",") m
上面的代码只会在四个模式匹配中的三个被注释掉的情况下编译。 "insert Person" 不能与 "deleteWhere" 一起玩,甚至不能与 "insert UnknownMessage" 一起玩。结果往往是类型匹配的错误消息,我经常无法做出正面或反面。
我该如何重写上面的代码?是否有针对任何地方受到单子挑战的持久指南?本书章节没有详细介绍如何链接查询等。
编辑:hammar 将 (>>) 添加到插入内容的建议解决了该问题。如果我删除“runDB $ do”,函数的类型变为“parseMsg :: PersistQuery backend m => String -> backend m ()”。这是否允许我稍后在 monad 中执行返回的查询,就像我在 Scala 中处理我的更新一样?
【问题讨论】:
你能给我们这样的错误信息吗?可能有助于了解正在发生的事情,而无需为我们这些不知道的人弄清楚是什么。 【参考方案1】:我不是 Yesod 专家,但从快速查看文档看来,问题在于 insert
操作返回新记录的键,而 updateWhere
和 deleteWhere
都返回 @987654325 @。
insert :: (...) => val -> backend m (Key backend val)
updateWhere :: (...) => [Filter val] -> [Update val] -> backend m ()
deleteWhere :: (...) => [Filter val] -> backend m ()
想必这里的key你并不关心,所以你可以通过做丢弃它
insert PersonpersonName = name >> return ()
应该进行类型检查。
【讨论】:
另见:void 另见:insert_ :: val -> m ()以上是关于Monad 在从 Lift 移植到 Yesod 的 Persistent 时遇到了麻烦的主要内容,如果未能解决你的问题,请参考以下文章