Опаловый запрос от String to Maybe

Я хочу выполнить запрос к моей таблице для заданного значения и вернуть Maybe a в зависимости от того, была ли найдена строка.

У меня есть этот домен:

data User' a b c d e f = User {  usrId :: a,
                                     usrApproved :: b,
                                     usrIden :: c, 
                                     usrImgUrl :: d,
                                     usrTitle :: e, 
                                     usrUrl :: f 
                                  }

type User = User' Int Bool String String String String

$(makeAdaptorAndInstance "pUser" ''User')

type UserColumn = User' (Column PGInt4) (Column PGBool) (Column PGText) (Column PGText) (Column PGText) (Column PGText) 

и следующие определения для таблицы и запросов:

userTable :: Table UserColumn UserColumn
userTable = Table "user" (pUser User {  usrId       = required "id",
                                                usrApproved = required "approved",
                                                usrIden     = required "identifier",
                                                usrImgUrl   = required "img_url",
                                                usrTitle    = required "title",
                                                usrUrl      = required "url"
                                             })

userQuery :: Query UserColumn
userQuery = queryTable userTable

Как указывалось ранее, я хочу сделать запрос по столбцу "идентификатора", поэтому я написал этот запрос и хочу вернуть `IO (может быть, пользователь)

userByIdenQuery :: (Column PGText) -> Query UserColumn
userByIdenQuery iden = proc () -> do
  user <- userQuery -< ()
  restrict -< (adIden user) .=== iden
  returnA -< user    

getUserByIden :: String -> PGS.Connection -> IO (Maybe User)
getUserByIden iden c = do
  usr <- runQuery c (userByIdenQuery $ pgString iden)
  -- But this fails to compile
  undefined -- just to minimise compilation errors

это не компилируется с:

No instance for (Default
                   Opaleye.Internal.RunQuery.QueryRunner UserColumn haskells0)
  arising from a use of `runQuery'
The type variable `haskells0' is ambiguous
Note: there is a potential instance available:
  instance (product-profunctors-0.7.1.0:Data.Profunctor.Product.Class.ProductProfunctor
              p,
            Default p a1_0 a1_1, Default p a2_0 a2_1, Default p a3_0 a3_1,
            Default p a4_0 a4_1, Default p a5_0 a5_1, Default p a6_0 a6_1) =>
           Default
             p
             (User' a1_0 a2_0 a3_0 a4_0 a5_0 a6_0)
             (User' a1_1 a2_1 a3_1 a4_1 a5_1 a6_1)
    -- Defined at src\DB.hs:33:3
In a stmt of a 'do' block:
  usr <- runQuery c (userByIdenQuery $ pgString iden)
In the expression:
  do { usr <- runQuery c (userByIdenQuery $ pgString iden);
       undefined }
In an equation for `getUserByIden':
    getUserByIden iden c
      = do { usr <- runQuery c (userByIdenQuery $ pgString iden);
             undefined }

Если я попытаюсь реализовать функцию:

getUserByIden :: String -> PGS.Connection -> IO (Maybe User)
getUserByIden iden c = do
  (usrId, appr, idn, imUrl, tit, url) <- runQuery c (userByIdenQuery $ pgString iden)
  return $ Just $ User usrId appr idn imUrl tit url

Затем я получаю эту ошибку компиляции:

Couldn't match expected type `[haskells0]'
        with actual type `(Int, Bool, String, String, String, String)'
In the pattern: (usrId, appr, idn, imUrl, tit, url)
In a stmt of a 'do' block:
  (usrId, appr, idn, imUrl, tit, url) <- runQuery
                                          c (userByIdenQuery $ pgString iden)
In the expression:
  do { (usrId, appr, idn, imUrl, tit, url) <- runQuery
                                               c (userByIdenQuery $ pgString iden);
       return $ Just $ User usrId appr idn imUrl tit url }

I really have no idea where to go with this, other than using a library other than Opaleye.

2 ответа

Решение

Я не знаком с OpalEye, но я думаю, что вам может понадобиться разумное использование listToMaybe (import Data.Maybe (listToMaybe))

getUserByIden :: String -> PGS.Connection -> IO (Maybe User)
getUserByIden iden c = do
  listToMaybe <$> runQuery c (userByIdenQuery $ pgString iden)

Я думаю, что проблема заключается в том, что вы используете undefined в конце вашей функции getUserByIden, Из-за некоторого сложного уровня магии, который Opaleye делает под капотом, вам нужно указать тип для использования runQueryили просто вернуть полученное значение вместо undefined, потому что undefined немного отбрасывает алгоритм верхнего вывода:

getUserByIden :: String -> PGS.Connection -> IO (Maybe User)
getUserByIden iden c = listToMaybe <$> runQuery c (userByIdenQuery $ pgString iden)

Я также добавил listToMaybe вызов, чтобы изменить тип тела функции в соответствии с указанным вами типом возвращаемого значения. runQueryпри полном применении возвращает значение типа IO [SomeHaskellType]не IO (Maybe SomeHaskellType),

Другие вопросы по тегам