【发布时间】:2019-11-09 15:15:48
【问题描述】:
我有两种类型 (<->) 和 (<-->) 代表类型之间的同构:
data Iso (m :: k -> k -> *) a b = Iso { to :: m a b, from :: m b a }
type (<->) = Iso (->)
infix 0 <->
data (<-->) a b = Iso' { to' :: a -> b, from' :: b -> a }
infix 0 <-->
两者之间的唯一区别是(<->) 是更通用类型的特化。
我可以很容易地coerce(<-->) 同构:
coerceIso' :: (Coercible a a', Coercible b b') => (a <--> b) -> (a' <--> b')
coerceIso' = coerce
但是当我尝试使用 (<->) 同构时出现错误:
coerceIso :: (Coercible a a', Coercible b b') => (a <-> b) -> (a' <-> b')
coerceIso = coerce
{-
src/Data/Iso.hs:27:13: error:
• Couldn't match type ‘a’ with ‘a'’ arising from a use of ‘coerce’
‘a’ is a rigid type variable bound by
the type signature for:
coerceIso :: forall a a' b b'.
(Coercible a a', Coercible b b') =>
(a <-> b) -> a' <-> b'
at src/Data/Iso.hs:25:1-73
‘a'’ is a rigid type variable bound by
the type signature for:
coerceIso :: forall a a' b b'.
(Coercible a a', Coercible b b') =>
(a <-> b) -> a' <-> b'
at src/Data/Iso.hs:25:1-73
-}
我目前的解决方法是分别强制执行前进和后退功能:
coerceIso :: (Coercible a a', Coercible b b') => (a <-> b) -> (a' <-> b')
coerceIso (Iso f f') = Iso (coerce f) (coerce f')
但是为什么需要这样的解决方法呢?为什么不能直接强制(<->)?
【问题讨论】:
-
好的,我想我明白了。有一个隐含的
type role Iso representational nominal nominal,因为编译器无法预测m的参数是名义上的还是代表性的,所以它很安全。现在我只希望有一种方法可以要求type role m representational representational -
在这个 GHC 提案实施后可以指定这样的类型角色:github.com/ghc-proposals/ghc-proposals/pull/233我昨天遇到了类似的问题。