2

我是 Haskell 的新手,来自 Scala。我喜欢 Haskell,但在使用persistent.

我的要求:我想将一些插入逻辑分离到它自己的方法中。我无法完全弄清楚类型或正确的方法。我所有失败的尝试都不会编译。更简洁的问题如下。

这是数据声明:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Curator
  name String
  url String
  feed String
  UniqueUrl url
  deriving Show
Article
  url String
  title String
  content String
  curatorId CuratorId Eq
  deriving Show
|]

这是一次失败的尝试,但不起作用:

insertArticle :: String -> String -> String -> MaybeT (???)
insertArticle url title content = do
    curatorId <- selectFirst [curatorName ==. "Fake Name"]
    lift $ do
        curator <- curatorId
        insert (Article url title content curator)

所以,我的问题:

  1. 应该是什么类型???
  2. lift在正确的地方吗?(通常编译器更有帮助)。
  3. 有一个更好的方法吗?

PS - 我已经成功地抽象了其他逻辑,例如插入只是给我带来了一个痛苦的世界。使用时我无法编译它SqlPersistM

getFeeds :: SqlPersistM [Curator]
getFeeds = do
  curatorIds <- selectList [] [Asc CuratorName]
  let curatorGenerics = map entityVal curatorIds
  let curators = map (\x -> x :: Curator) curatorGenerics
  return curators
4

1 回答 1

1

的返回类型insertArticle应该是SqlPersistM (Maybe ArticleId),因为它返回Just一个插入的文章 id 或NothingSqlPersistMmonad 中。

您可以实现以下功能:

insertArticle :: String -> String -> String -> SqlPersistM (Maybe ArticleId)
insertArticle url title content = do
    curatorEntity <- selectFirst [CuratorName ==. "Fake Name"] []
    for curatorEntity $ \(Entity curatorId _) ->
        insert (Article url title content curatorId)

我在这里使用forfromData.Traversable来处理返回MaybeselectFirst

但是,实际上,我不喜欢这种类型签名,因为它坚持 sql 后端。为了使其更通用,您可以编写这样的类型注释。

insertArticle :: (Applicative m, PersistQuery m, PersistMonadBackend m ~ PersistEntityBackend Curator) =>
                 String -> String -> String -> m (Maybe ArticleId)

签名有点复杂,但这个函数适用于任何后端。

顺便说一句,你getFeeds可以简化。

getFeeds :: (Functor m, PersistQuery m, PersistMonadBackend m ~ PersistEntityBackend Curator) =>
            m [Curator]
getFeeds = map entityVal <$> selectList [] [Asc CuratorName]
于 2013-08-07T04:51:34.300 回答