valderman / selda

A type-safe, high-level SQL library for Haskell
https://selda.link
MIT License
478 stars 58 forks source link

not able to use GeneralizedNewtypeDeriving to derive SqlRow on newtype #152

Open cdepillabout opened 3 years ago

cdepillabout commented 3 years ago

I'm somewhat surprised that I am not able to use GeneralizedNewtypeDeriving to derive SqlRow on a newtype.

Here's a small example of the code that I'm trying to write:

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}

module Example where

import Database.Selda

data Foo = Foo
  { a :: Int
  , b :: Text
  }
  deriving stock (Eq, Generic, Show)
  deriving anyclass (SqlRow)

newtype Bar = Bar Foo
  deriving stock (Eq, Show)
  deriving newtype (Generic, SqlRow)

When trying to compile this, I get the error:

Example.hs:20:30: error:
    • Couldn't match type ‘Foo’ with ‘Bar’
        arising from the coercion of the method ‘nextResult’
          from type ‘selda-0.5.2.0:Database.Selda.SqlRow.ResultReader Foo’
            to type ‘selda-0.5.2.0:Database.Selda.SqlRow.ResultReader Bar’
    • When deriving the instance for (SqlRow Bar)
   |
20 |   deriving newtype (Generic, SqlRow)
   |             

After playing around with this for a little bit, I realized it is possible to write the SqlRow instance by hand, even though the ResultReader type is not exposed:

instance SqlRow Bar where
  nextResult = fmap Bar nextResult
  nestedCols _ = nestedCols (Proxy :: Proxy Foo)

Maybe this is just a non-issue. Hopefully this GitHub issue can help other users who stumble on it, but please feel free to just close it.

dhess commented 3 years ago

I have the same issue with SqlType, using a simple newtype wrapper around Text.

(edit Ahh, I see: #13)