postgresql - 带有 postgresql-simple 的嵌套类型的 FromRow 实例

标签 postgresql haskell

我使用以下类型来表示用户:

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),因此错误提示它无法将 aCredentialsRep upb 匹配> 使用 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/

相关文章:

sql - PostgreSQL:如何将字符串列表作为表进行搜索?

postgresql - 如何更改 PostgreSql 数据库的所有者?

haskell - Haskell 有类似 Incanter 的东西吗?

algorithm - 在 Haskell 中实现 Karatsuba 算法

haskell - J 风格的副词、 fork 等是否通过主流函数式语言的库进行了模拟?

postgresql - 错误 | sudo apt-get 更新:404 未找到 [IP:2604:1380:2000:7501::69 80]

postgresql - 如何减少存储(缩小)我的 RDS 实例?

haskell - 相互递归函数的 Hindley Milner 类型推理

sql - 如何在where子句中使用column default来标识默认值

haskell - 模式匹配的变量值