我使用以下类型来表示用户:
data CredentialsRep uType pType = Credentials { username :: uType
, password :: pType } deriving (Show)
data NameRep fType lType = Name { first :: fType
, last :: lType } deriving (Show)
data UserRep cType nType = User { credentials :: cType
, name :: nType} deriving (Show)
如何为 UserRep
编写 FromRow
实例,以便 postgresql-simple
可以将我的查询转换为有用的类型?到目前为止,我有这个:
instance FromRow (UserRep a b) where
fromRow = do
username <- field
password <- field
fname <- field
lname <- field
return $ (User (Credentials username password) (Name fname lname))
导致此错误的原因:
src/PSQLTEST.hs:30:5:
Couldn't match type ‘a’ with ‘CredentialsRep uType0 pType0’
‘a’ is a rigid type variable bound by
the instance declaration at src/PSQLTEST.hs:24:10
Expected type: RowParser (UserRep a b)
Actual type: RowParser
(UserRep (CredentialsRep uType0 pType0) (NameRep fType0 lType0))
Relevant bindings include
password :: pType0 (bound at src/PSQLTEST.hs:27:5)
username :: uType0 (bound at src/PSQLTEST.hs:26:5)
fromRow :: RowParser (UserRep a b) (bound at src/PSQLTEST.hs:25:3)
In a stmt of a 'do' block:
return $ (User (Credentials username password) (Name fname lname))
In the expression:
do { username <- field;
password <- field;
fname <- field;
lname <- field;
.... }
In an equation for ‘fromRow’:
fromRow
= do { username <- field;
password <- field;
fname <- field;
.... }
src/PSQLTEST.hs:30:5:
Couldn't match type ‘b’ with ‘NameRep fType0 lType0’
‘b’ is a rigid type variable bound by
the instance declaration at src/PSQLTEST.hs:24:10
Expected type: RowParser (UserRep a b)
Actual type: RowParser
(UserRep (CredentialsRep uType0 pType0) (NameRep fType0 lType0))
Relevant bindings include
lname :: lType0 (bound at src/PSQLTEST.hs:29:5)
fname :: fType0 (bound at src/PSQLTEST.hs:28:5)
fromRow :: RowParser (UserRep a b) (bound at src/PSQLTEST.hs:25:3)
In a stmt of a 'do' block:
return $ (User (Credentials username password) (Name fname lname))
In the expression:
do { username <- field;
password <- field;
fname <- field;
lname <- field;
.... }
In an equation for ‘fromRow’:
fromRow
= do { username <- field;
password <- field;
fname <- field;
.... }
最佳答案
(免责声明:我根本没用过这个库)
您正在尝试为所有 UserRep a b
定义 FromRow
,但是在 fromRow
的定义中您显式构造了一个 UserRep (CredentialsRep up) (NameRep fl)
,因此错误提示它无法将 a
与 CredentialsRep up
和 b
匹配> 使用 NameRep f l
(模类型变量名称)。相反,我相信你可以做类似的事情
instance (FromField u, FromField p, FromField f, FromField l) => FromRow (UserRep (CredentialsRep u p) (NameRep f l)) where
fromRow = do
username <- field
password <- field
firstname <- field
lastname <- field
return $ User (Credentials username password) (Name firstname lastname)
或者只是
instance FromRow (UserRep (CredentialsRep String String) (NameRep String String)) where
...
具有相同的 fromRow
定义。使用这种方法,您可能必须启用 FlexibleInstances
扩展。
此外,看起来你的类型可能过于多态(但你的情况可能是独一无二的,对这个建议持保留态度),你可以完全摆脱类型参数并拥有
data CredentialsRep = Credentials
{ username :: String
, password :: String
} deriving (Show)
data NameRep = Name
{ first :: String
, last :: String
} deriving (Show)
data UserRep = User
{ credentials :: CredentialsRep
, name :: NameRep
} deriving (Show)
在这种情况下你只需要
instance FromRow UserRep where
...
具有相同的 fromRow
定义。
关于postgresql - 带有 postgresql-simple 的嵌套类型的 FromRow 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29930717/