不幸的是,Coercible (f a) (f (Decorated s a))
真的是你在给定GHC当前状态的约束下想要的。现在,其他s
和a
没有出现在其他地方的事实并不好 - 这意味着GHC不会知道如何处理它们(它们是模棱两可的)!我不会成...
根据送入类型构造f
类型参数的role,Coercible a b
可能会或可能不会暗示Coercible (f a) (f b)
。在这种情况下,我们希望这个角色是名义上的 - 但是没有(至少)有一种方式来表达这种约束。为了解释我的意思,考虑以下两个数据定义:
{-# LANGUAGE TypeFamilies #-}
import Data.Coerce
-- type role of `a` is "representational"
data Data1 a = Data1 a
-- type role of `a` is "nominal"
data Data2 a = Data2 (TypeFunction a)
type family TypeFunction x where
TypeFunction Bool = Char
TypeFunction _ =()
然后,当它是真实的Coercible a b
需要Coercible (Data1 a) (Data1 b)
,它不意味着Coercible (Data2 a) (Data2 b)
。为了使这个混凝土,加载在GHCI上面,然后尝试:
ghci> newtype MyInt = My Int
ghci> let c1 = coerce :: (Data1 MyInt) -> (Data1 Int)
ghci> let c2 = coerce :: (Data2 MyInt) -> (Data2 Int) -- This doesn't work!
不幸的是,执行一个类型变量的作用是代表性的没有内置的基于约束的方式。您可以为此创建自己的类,如Edward Kmett has done,但GHC不会像Coercible
的类实例那样自动创建这些类中的某些类的实例。
这导致this TRAC票,他们讨论与像生成Coercible
可能有事情像
instance (Representational f, Coercible a b) => Coercible (f a) (f b)
如果今天实际上是一个东西,实例的类Representational f
的可能性,所有你需要在你的约束将是Representational f
。此外,正如理查德艾森伯格在票上所说的,我们真的应该能够弄清楚f a
中的a
对于任何合理的函子f
都具有代表性。那么,我们可能甚至不需要在Functor f
之上的任何约束,因为Representational
可能是Functor
的超类。
Here is a good discussion of the current limitations of roles.
'myFunction'已经不能编译,因为类型's'没有提到在函数的类型(如你所指出的那样),所以'CTX s'从'fancyFunction'产生会导致一个模糊的类型错误(即使'fancyFunction。undefined'也会产生这样的错误)。在任何情况下,它都会看到你想要一个函数'(Functor f,Coercible ab)=> fa - > fb',这在操作上就是身份,在这种情况下你可能会对[通用函数]感兴趣(https://hackage.haskell。 org/package/profunctors-5.2/docs/Data-Profunctor-Unsafe.html#v:-35-。) - 一般使用'不安全'的操作,但GHC会告诉你..“ – user2407038
”注:我们不知道什么角色参数到\'f';我们必须假定角色是名义上的“,如果您修复了不相关的模糊类型错误(例如通过移除'Ctx s'约束)。没有办法谈论类型变量的作用 - 这是一个已知的限制。 – user2407038
我很确定没有办法解决这个问题。问题是你想做什么可以或不可以做什么取决于任何'f'的角色。 [This](https://ghc.haskell.org/trac/ghc/ticket/9123)票证更详细。 [Here](https://github.com/ekmett/roles/blob/master/src/Data/Roles.hs)是Edward Kmett的替代方法之一。 – Alec