我有以下Haskell代码,可以完美编译:
import Control.Monad.Reader (Reader (..))
import Data.Coerce (Coercible, coerce)
data Flow i o = Flow (i -> o) (o -> i)
coerceFlow
:: (Coercible i i', Coercible o o')
=> Flow i o
-> Flow i' o'
coerceFlow = coerce
然而,如果我把Flow
类型的定义更改为以下内容:
data Flow i o = Flow (i -> Reader Int o) (o -> i)
我开始看到一个奇怪的错误:
Coerce.hs:10:14: error:
• Couldn't match type ‘o’ with ‘o'’ arising from a use of ‘coerce’
‘o’ is a rigid type variable bound by
the type signature for:
coerceFlow :: forall i i' o o'.
(Coercible i i', Coercible o o') =>
Flow i o -> Flow i' o'
at Coerce.hs:(6,1)-(9,17)
‘o'’ is a rigid type variable bound by
the type signature for:
coerceFlow :: forall i i' o o'.
(Coercible i i', Coercible o o') =>
Flow i o -> Flow i' o'
at Coerce.hs:(6,1)-(9,17)
• In the expression: coerce
In an equation for ‘coerceFlow’: coerceFlow = coerce
• Relevant bindings include
coerceFlow :: Flow i o -> Flow i' o' (bound at Coerce.hs:10:1)
|
10 | coerceFlow = coerce
| ^^^^^^
据我理解,我的数据类型不再自动可强制转换(Coercible)。有没有一种方法可以告诉 GHC 我可以自��强制转换
Flow
类型的值?我可以手动强制转换(coerce)每个字段,但我希望同时强制转换整个数据类型(这是必需的,以便DerivingVia
正常工作)。我尝试使用
RoleAnnotations
扩展,例如:type role Flow representational representational
但我看到了一个错误:
Coerce.hs:6:1: error:
• Role mismatch on variable o:
Annotation says representational but role nominal is required
• while checking a role annotation for ‘Flow’
|
6 | type role Flow representational representational
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ReaderT
(newtype
构造函数是重要部分),则确实会获得coerce ::(Coercible i i',Coercible o o')=> Reader i o-> Reader i' o'
。但是,即使导入了它,OP的代码也无法正常工作。似乎强制转换求解器忽略newtype
上的角色的能力不扩展到data
。我不确定这是否是有意还是疏忽或其他什么原因。 - HTNWcoerce
会这样转换类型。看起来 GHC 在 OP 的情况下展开了第一个data
定义,但没有展开第二个。 - chidata
和newtype
(只要所有相关构造函数都可见)。不过我不确定。 - HTNW