对于PersistFieldSql,GeneralizedNewtypeDeriving失败

时间:2014-09-17 14:20:03

标签: haskell newtype forall

我正在尝试定义Markdown新类型,并使用GeneralizedNewtypeDeriving自动定义新实例:

import Text.Markdown
import Yesod.Text.Markdown
import Database.Persist.Sql

newtype MarkdownNewT = MarkdownNewT { getMarkdown :: Markdown }
  deriving (Eq, IsString, Monoid, PersistField, PersistFieldSql)

PersistFieldSql失败,显示以下消息:

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’

这是否归功于GHC 7.8.2的新roles功能?在那种特殊情况下,我不知道该怎么做,因为Markdown本身就是Text的新类型......

或者这与forall上的sqlType有关吗?当所有其他实例成功自动派生时,出现此错误的原因是什么?

由于

1 个答案:

答案 0 :(得分:6)

这看起来与GHC wiki Roles2页面中与当前角色系统不兼容的一些示例(特别是Vector)非常相似,唉。

基本上问题在于

class PersistField a => PersistFieldSql a where
    sqlType :: Monad m => m a -> SqlType

monad m可能会使用其参数具有名义角色的类型构造函数进行实例化,因此m Markdownm MarkdownNewT 不会相同地表示,即使MarkdownMarkdownNewT本身就是 - 并且当前的角色系统无法限制m禁止此类型构造函数。