如何过滤 Esqueleto 中的 Just 字段?

How do I filter Just field in 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' 签名?

您尝试使用 (?.) 运算符从非 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)

我没有运行这个代码,只是编译了它。