circuithub / rel8

Hey! Hey! Can u rel8?
https://rel8.readthedocs.io
Other
150 stars 38 forks source link

Map Rel8able result to a separate Haskell type? #221

Closed remeike closed 1 year ago

remeike commented 1 year ago

So apologies ahead of time if this question is misguided, but I've been trying out Rel8 on a project recently and I was wondering if there's some way to easily map a Rel8able result to a separate Haskell type.

Say I have this data type that corresponds to a SQL table:

data DBUser f =
  DBUser
    { dbUserId    :: Column f Int64
    , dbUserEmail :: Column f Text
    , dbUserName  :: Column f Text
    }
  deriving stock (Generic)
  deriving anyclass (Rel8able)

usersTable :: TableSchema (DBUser Name)
usersTable =
  TableSchema
    { name   = "users"
    , schema = Nothing
    , columns =
        DBUser
          { dbUserId    = "id"
          , dbUserEmail = "email"
          , dbUserName  = "username"
          }
    }

queryUsers :: Query (DBUser Expr)
queryUsers =
  each usersTable

And then I have a similar type from my domain like so:

data User =
  User
    { userEmail :: Text
    , userName  :: Text
    }

What I'm trying to figure out is if there's some sort of type class instance I can add for User that makes it convenient to map from DBUser Result to User so that I can do this.

selectUsers :: Statement () [User]
selectUsers =
  select queryUsers

I took a look at the Serializable class but had a hard time wrapping my head around it.

For reference, I've used Opaleye a fair bit and there I would achieve something similar by doing this:

instance Default QueryRunner (DBUser Expr) User where
  def =
    (flip rmap) (def :: QueryRunner (DBUser Expr) (DBUser Result)) $
      \(DBUser _ email name) -> User email name

So I guess I'm just trying to figure out if there's a roughly similar convenience in Rel8. No worries if not! I've really enjoyed working with this library thus far!

tomjaguarpaw commented 1 year ago

Migrated to https://github.com/circuithub/rel8/discussions/222