nikita-volkov / hasql

The fastest PostgreSQL libpq-based driver for Haskell
http://hackage.haskell.org/package/hasql
MIT License
519 stars 55 forks source link

Could `Value` be representational? #137

Closed ocharles closed 3 years ago

ocharles commented 3 years ago

Currently Hasql.Decoders.Value takes a nominal type. This means that Values cannot be coerced. This is a bit of a shame, because we could imagine having

class HasValue a where
  value :: Value a

instance HasValue Bool where
  value = bool

newtype MyBool = MyBool Bool
  deriving newtype (HasValue)

I can work around this, because I can do:

class HasValue a where
  value :: Yoneda Value a

data Yoneda f a where
  Yoneda :: f x -> (x -> a) -> Yoneda f a

But this is obviously not ideal.

How do you feel about adding

type role Value representational

?

nikita-volkov commented 3 years ago

It refuses to compile.

Annotation says representational but role nominal is required

I even tried getting down to the root of the parser hierarchy, which is

newtype BinaryParser a =
  BinaryParser ( StateT ByteString ( Except Text ) a )
  deriving ( Functor , Applicative , Alternative , Monad , MonadPlus , MonadError Text )

type role BinaryParser representational

And it fails for the same reason.

ocharles commented 3 years ago

Hmm, I wonder what is causing it be nominal. Perhaps it gets all the way down to StateT being nominal? What if you explicitly write out BinaryParser (ByteString -> Either Text (a, ByteString))?

nikita-volkov commented 3 years ago

You're right! The fix will be released in 1.4.5 in minutes.

Lack of coercibility has been a long observed issue which I didn't understand the roots of. I guess I've learned something today :) Thanks!

ocharles commented 3 years ago

Hurrah, thanks @nikita-volkov! Now we can remove our hacky workaround :)

nikita-volkov commented 3 years ago

Sorry. Forgot to actually publish the package :) Now it's on Hackage.