2016-09-03 19 views
0

我想對我的表運行鍼對給定值的查詢,並根據是否找到一行返回Maybe aOpaleye按字符串查詢到Maybe

我有這個域名:

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 

這個失敗無法編譯wi日:

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. 
+1

'runQuery'有一個非常普遍的返回類型 - 給它一個類型簽名,或者返回一個類型簽名。 [docs](https://hackage.haskell.org/package/opaleye-0.5.0.0/docs/Opaleye-RunQuery.html)非常清楚地表明:「runQuery使用Default typeclass意味着編譯器將無法推斷強烈建議您在使用runQuery時提供完整類型的簽名。「 – user2407038

+0

如何準確提供類型簽名?黑線鱈總是讓我困惑。 –

+1

從某種意義上說,你已經給它一個類型簽名 - 'getUserByIden :: String - > PGS.Connection - > IO(也許用戶)' - 但是'usr'在主體中是未使用的,所以它不能與'User' 。如果你真的實現了這個功能,這可能就足夠了。與此同時,您可以通過多種方式編寫類型簽名:'(x :: X)< - a'或'x < - a :: IO X'或'_x < - a;讓x :: X; x = _x' – user2407038

回答

3

我不熟悉OpalEye,但我想你可能只需要明智地使用listToMaybeimport Data.Maybe (listToMaybe)

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

我認爲問題在於您在函數getUserByIden的末尾使用undefined。由於Opaleye的一些複雜類型魔法正在引擎蓋下,因此您需要指定一個類型以使用runQuery,或者只是返回生成的值而不是未定義的值,因爲undefined會拋棄頂部推理算法一點點:

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

我還添加了一個listToMaybe調用來更改函數主體的類型以匹配您指定的返回類型。 runQuery在完全應用時返回類型爲IO [SomeHaskellType]的值,而不是IO (Maybe SomeHaskellType)

+0

謝謝。另一個答案(類似的內容)在你的之前發佈,所以我接受了他們的答案。感謝您的幫助! –