以下はSet.mapMonotonic coerce
と同じくらい安全だと思います。つまり、Set
またはa
に異なるb
インスタンスがある場合、起こりうる最悪の事態はOrd
不変式を壊すことです。
coerceSet :: Coercible a b=> Set.Set a -> Set.Set b
coerceSet = unsafeCoerce
あれは正しいですか?
[〜#〜] edit [〜#〜]:Set
に関連する機能の問題: https:// github .com/haskell/containers/issues/308
これすべき安全です。
有効なcoerce @a @b
は、常に有効なunsafeCoerce @a @b
で置き換えることができます。どうして?コアレベルでは、これらはcoerce
(id
のように入力を返すだけ)の同じ関数だからです。 coerce
は、強制される2つのものが同じ表現であることの証明を引数として取るということです。通常のcoerce
の場合、この証明は実際の証明ですが、unsafeCoerce
の場合、この証明は、「信頼してください」というトークンにすぎません。この証明は型引数として渡されるため、型消去によってプログラムの動作に影響を与えることはありません。したがって、unsafeCoerce
とcoerce
は、両方が可能な場合は常に同等です。
Set
はcoerce
では機能しないため、これでSet
の話は終わりではありません。どうして?その定義をのぞいてみましょう。
data Set a = Bin !Size !a !(Set a) !(Set a) | Tip
この定義から、a
はどの型の等式の内部にも現れないことがわかります。これは、Set
で表現型の等値の合同があることを意味します:if a ~#R b
(if a
はb
と同じ表現を持ち、~#R
はボックス化解除されたCoercible
)であり、次にSet a ~#R Set b
です。したがって、Set
だけの定義から、coerce
shouldSet
を処理し、したがってunsafeCoerce
すべき安全です。 containers
ライブラリは特定の
type role Set nominal
この事実を世界から隠すには、coerce
を人為的に無効にします。ただし、unsafeCoerce
を無効にすることはできません。繰り返しますが、unsafeCoerce
(このコンテキストでは)は安全です。
(unsafeCoerce
とcoerce
の型が同じになるように注意してください!「熱狂的」な型の推論がすべてを形から曲げる状況の例については、@ dfeuerの回答を参照してください。)
はい、これは通常の現実的な状況では安全です。しかし、それはisであるが、そうでない場合の不自然な例を考え出すことは可能です。デフォルトを使用するものは次のとおりです。重複するインスタンスや他の奇抜な機能を使用して同様のことを実行できる可能性があると想像しますが、わかりません。
{-# language GADTs, TypeOperators, ExistentialQuantification #-}
import Data.Coerce
import Unsafe.Coerce
import Data.Type.Equality
data Buh a = Buh (a :~: Rational) a
data Bah = forall a. Bah (a :~: Rational) a
instance Show Bah where
show (Bah Refl x) = show x
goo :: Rational -> Bah
goo x = case coerce p of
Buh pf m ->
let _q = truncate m
in Bah pf 12
where
p = Buh Refl x
goo
を呼び出すと、すべてうまくいきます。 coerce
をunsafeCoerce
に置き換えた場合、goo
を呼び出すと、セグメンテーション違反が発生したり、他の問題が発生したりします。