问题
I'm trying to define a Markdown newtype, and using GeneralizedNewtypeDeriving
to automatically define new instances:
import Text.Markdown
import Yesod.Text.Markdown
import Database.Persist.Sql
newtype MarkdownNewT = MarkdownNewT { getMarkdown :: Markdown }
deriving (Eq, IsString, Monoid, PersistField, PersistFieldSql)
This fails for the PersistFieldSql
with the following message:
Could not coerce from ‘m Markdown’ to ‘m MarkdownNewT’
because ‘m Markdown’ and ‘m MarkdownNewT’ are different types.
arising from the coercion of the method ‘sqlType’ from type
‘forall (m :: * -> *). Monad m => m Markdown -> SqlType’ to type
‘forall (m :: * -> *). Monad m => m MarkdownNewT -> SqlType’
Is this due to the new roles features of GHC 7.8.2? In that particular case I don't know what to do, since Markdown is itself a newtype over Text...
Or is this related with the forall
on sqlType
? What is the reason for this error when all other instances are successfully automatically derived?
Thanks
回答1:
This looks very similar to some of the examples (in particular the Vector
one) in the GHC wiki Roles2 page of things that don't work with the current role system, alas.
Basically the problem is that in
class PersistField a => PersistFieldSql a where
sqlType :: Monad m => m a -> SqlType
the monad m
might be instantiated with a type constructor whose argument has nominal role, so that m Markdown
and m MarkdownNewT
aren't identically represented even if Markdown
and MarkdownNewT
themselves are - and the current role system has no way of restricting m
to disallow such type constructors.
来源:https://stackoverflow.com/questions/25893150/generalizednewtypederiving-fails-for-persistfieldsql