如何在Esqueleto中过滤Just field?

时间:2018-02-09 04:53:29

标签: haskell esqueleto

使用以下持久架构

Picture
  bytes ByteString
  desc Text Maybe

我想查询SELECT id, desc FROM picture WHERE desc IS NOT NULL。但

previews :: SqlPersistT Handler [(E.Value (Key Picture), E.Value Text)]
previews = E.select $ from $ \pics -> do
  where_ $ pics ?. PictureDesc E.!=. nothing
  return ( pics ^. PictureId
         , pics ?. PictureDesc
         )

• Couldn't match type ‘Maybe (Entity Picture)’
                 with ‘Entity Picture’
  Expected type: SqlExpr (Entity Picture)
    Actual type: SqlExpr (Maybe (Entity Picture))
• In the first argument of ‘(^.)’, namely ‘pics’

如何实现previews'签名σ

1 个答案:

答案 0 :(得分:0)

您尝试使用(?.)运算符从非Maybe实体的Maybe字段中获取非Maybe值,但它的作用是从Maybe实体中的非Maybe字段中获取Maybe值。在这里,您的实体实际上不是Maybe,因为它不是外部联接的结果。

我不认为在没有不安全函数的情况下返回Value Text是不可能的,因为使用where_进行过滤不会将可空字段的类型更改为不可为空。 (在我看来,应该有一个投影操作员做你想做的事。)

所以你可以这样做

previews :: SqlPersistT Handler [(Value (Key Picture), Value (Maybe Text))]
previews = select $ from $ \pics -> do
  where_ $ not_ . isNothing $ pics ^. PictureDesc
  return ( pics ^. PictureId
         , pics ^. PictureDesc
         )

或删除Maybe,使用Control.Arrow的second和Data.Maybe的fromJust,尽管可能有更优雅的方式:

previews' :: SqlPersistT Handler [(Value (Key Picture), Value Text)]
previews' = do
  xs <- select $ from $ \pics -> do
    where_ $ not_ . isNothing $ pics ^. PictureDesc
    return ( pics ^. PictureId
           , (pics ^. PictureDesc)
           )
  return (map (second $ fmap fromJust) xs)

我没有运行此代码,只编译它。