不幸的是,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