2

我有一个 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 Person{personName = name}
        ["delete",name]    -> deleteWhere [PersonName ==. name]
        ["change",from,to] -> updateWhere [PersonName ==. from] [PersonName =.to]
        _                  -> insert UnknownMessage{unknownMessageText = m}
where
    ms = splitRegex (mkRegex ",") m

上面的代码只会在四个模式匹配中的三个被注释掉的情况下编译。"insert Person" 不能与 "deleteWhere" 一起玩,甚至不能与 "insert UnknownMessage" 一起玩。结果往往是类型匹配的错误消息,我经常无法做出正面或反面。

我该如何重写上面的代码?是否有针对任何地方受到单子挑战的持久指南?本书章节没有详细介绍如何链接查询等。

编辑:hammar 建议在插入中添加 (>>) 解决了这个问题。如果我删除“runDB $ do”,函数的类型变为“parseMsg :: PersistQuery backend m => String -> backend m ()”。这是否允许我稍后在 monad 中执行返回的查询,就像我在 Scala 中处理我的更新一样?

4

1 回答 1

4

我不是 Yesod 专家,但从快速查看文档看来,问题在于该insert操作返回新记录的键,而updateWhere两者deleteWhere都返回()

insert      :: (...) => val -> backend m (Key backend val)
updateWhere :: (...) => [Filter val] -> [Update val] -> backend m ()
deleteWhere :: (...) => [Filter val] -> backend m ()

大概,你不关心这里的密钥,所以你可以通过做丢弃它

insert Person{personName = name} >> return ()

这应该使其类型检查。

于 2012-09-27T19:11:43.590 回答