Haskell + Yesod:使用Persistent分离插入逻辑将无法编译。无法弄清楚类型

时间:2013-08-07 03:38:51

标签: haskell yesod

我是来自Scala的Haskell的新手。我喜欢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. 有更好的方法吗?
  4. 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
    

1 个答案:

答案 0 :(得分:1)

insertArticle的返回类型应为SqlPersistM (Maybe ArticleId),因为它会在Just monad中返回Nothing插入的文章ID或SqlPersistM

您可以实现以下功能:

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)

我使用for中的Data.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]