問題が解決しない:それはまだcoerce
でだまさすることができます、と私はコンパイル時に、それをブロックする方法を探していますが
コンストラクターが範囲内にある限り、newtype
はその表現に対して強制的です。実際、これはCoercible
の動機の大きな部分です。 Coercible
の制約は、他の型のクラス制約と似ていて、自動的に検索されてまとめられます。あなたとしておそらく - あなたはContainer
コンストラクタをエクスポートしない場合はこのように、coerce c3
あなたはすべてのp
とp'
、と喜ん
instance (Coercible a b, Coercible b c) => Coercible a c
を経由してあなたのための複合強制を構築するための
instance Coercible (Container p) [Int]
instance Coercible [Int] (Container p')
を持っていることを見つけることですとにかくやりたい!あなたはいつものことができます、しかし
ContainerClient.hs:13:6:
Couldn't match type ‘4’ with ‘3’
arising from trying to show that the representations of
‘Container 3’ and
‘Container 4’ are the same
Relevant role signatures: type role Container nominal nominal
In the expression: coerce c3
In an equation for ‘c4’: c4 = coerce c3
: - それはもはやnewtype
はその表現に等しいことが知られています(あなたは、上記の最初の2つのインスタンスを失っていない)、そして、あなたは他のモジュールで必要なエラーが出ますnewtype
(coerce
またはそれ以外の方法で)を定義するモジュールでインバリアントを解除します。サイドノートとして
、おそらくは、ここでは、レコード形式のアクセサを使用し、それをエクスポートする必要はありません。ユーザーがレコードの更新構文を使用してコードを変更することができるようにするため、
が有効になります。代わりにrunContainer
をフリースタンディング関数にしてください。
我々は(-ddump-simpl
経由)コアを見て2つのnewtype
-representation制約の組成を取得していることを確認することができますContainer
を定義するモジュール内の(私もContainer
呼ばれてきました)、 NTCo
はnewtype
Container p
と、それとの間にnewtype
強制である:(私たちはエクスポートリストを削除する場合)出力が
c4 :: Container 4
[GblId, Str=DmdType]
c4 =
c3
`cast` (Container.NTCo:Container[0] <GHC.TypeLits.Nat>_N <3>_N
; Sym (Container.NTCo:Container[0] <GHC.TypeLits.Nat>_N <4>_N)
:: Container 3 ~R# Container 4)
それが読み少し難しいですが、見るべき重要なことはContainer.NTCo:Container[0]
ですs表現タイプ。Sym
はこれを変え、;
は2つの制約を構成します。
最終的な制約γₓ
を呼び出します。その後、全体のタイピングの導出はここ
Sym :: (a ~ b) -> (b ~ a)
-- Sym is built-in
(;) :: (a ~ b) -> (b ~ c) -> (a ~ c)
-- (;) is built-in
γₙ :: k -> (p :: k) -> Container p ~ [Int]
γₙ k p = Container.NTCo:Container[0] <k>_N <p>_N
γ₃ :: Container 3 ~ [Int]
γ₃ = γₙ GHC.TypeLits.Nat 3
γ₄ :: Container 4 ~ [Int]
γ₄ = γₙ GHC.TypeLits.Nat 4
γ₄′ :: [Int] ~ Container 4
γ₄′ = Sym γ₄
γₓ :: Container 3 ~ Container 4
γₓ = γ₃ ; γ₄′
である私が使用したソースファイルは、次のとおりです。
Container.hs:
{-# LANGUAGE FlexibleContexts, UndecidableInstances, ScopedTypeVariables,
RoleAnnotations, PolyKinds, DataKinds #-}
module Container (Container(), runContainer) where
import Data.Proxy
import Data.Reflection
import Data.Coerce
newtype Container p = Container { runContainer :: [Int] }
deriving (Eq, Show)
type role Container nominal
instance Reifies p Integer => Monoid (Container p) where
mempty = Container $ replicate (fromIntegral (reflect (Proxy :: Proxy p))) 0
mappend (Container l) (Container r) = Container $ l ++ r
c3 :: Container 3
c3 = mempty
-- Works
c4 :: Container 4
c4 = coerce c3
ContainerClient.hs:
{-# LANGUAGE DataKinds #-}
module ContainerClient where
import Container
import Data.Coerce
c3 :: Container 3
c3 = mempty
-- Doesn't work :-)
c4 :: Container 4
c4 = coerce c3
GHC 7.10は 'LANGUAGE'アノテーションがないために多くのエラーを投げますあなたの元のコードで。あなたはそれらを追加できますか? – Zeta
'.hs'ファイルで何が起こるのか確認しましたか? GHCiはモジュールの境界に関して奇妙なことがあります。私は 'hyperloglog'が独自の役割宣言を持っていると確信しています。 – dfeuer
奇妙なこと...役割の注釈は実際にこれらの強制を防ぐべきです。 – chi