メソッドを持たない2つのクラスを用意しましょう。もう1つはサブクラスです。 さらに、タイプがunsafeCoerce
の関数f5
とf6
を想定します。余分な関数の制約を取り除くにはどうすればよいですか?
ghciは、これらの関数を構成し、ScopedTypeVariablesの助けを借りてシグネチャを見つけることができます(f56, f56b and f56'
を参照)。 これらは基本的に制約Hmm
を持つ関数です。
それはそれは、制約の中でクラス
SHmm
を参照 せずにそれを書くされ、f56c
を書くことは可能ですか?例えば。いくつかの言語プラグマの助けを借りてこの をghciでコンパイルできますか?クラスにメソッドがない場合、
unsafeCoerce
を使用するとどんな危険がありますか? (またはサブクラスSHmm
にはメソッドがありません) への他の方法/推奨方法はありますかf5
とf6
?それだけでf56 = f5 . f6
を書き込むことはできませんので、なぜf5
とf6
次のコードで
そして最後の一つとしては、自分の署名を持っていますか? (特に場合はSHmm
はf56
を書くときにその制約SHmm
が必要とされていないと考えることは簡単である理由である、空の場合。)
{-# LANGUAGE ScopedTypeVariables, KindSignatures, MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes, FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
import Unsafe.Coerce
class Hmm (f :: *)
class Hmm f => SHmm f
f5 :: (Hmm m1, SHmm m) => m -> m1
f5 = unsafeCoerce
f6 :: (Hmm m, SHmm m1) => m -> m1
f6 = unsafeCoerce
f56 :: forall m1 m2 m3. (Hmm m3, Hmm m2, SHmm m1) => m3 -> m2
f56 = f5 . (f6 :: m3 -> m1)
f56b :: forall m1 m2. (Hmm m2, SHmm m1) => m2 -> m2
f56b = f5 . (f6 :: m2 -> m1)
-- f56c :: forall m2. Hmm m2 => m2 -> m2
-- f56c = f5 . (f6 :: SHmm m1 => m2 -> m1)
f56' :: forall m1 m2 m3. (Hmm m3, Hmm m2, SHmm m1) => m3 -> m2
f56' a = f5 $ (f6 :: m3 -> m1) a
「安全でない」ものに魅力を感じるのはなぜですか?実際に何を達成しようとしていますか? – chi
他の人が言っているように、これは本当に意味をなさないものです。あなたは 'Data.Coerce'で' Coercible'疑似クラスをチェックするのが面白いかもしれません。それはいくつかのかなり強力な強制的な機械です。 'Data.Type.Coercion'でそれを扱うためのツールがいくつかあります。 'coerce'関連の書き換えルールにも注意してください。 'containers'パッケージには、私が数年前に書いた良い例がいくつかあります。安全ではない強制変換は、(ある種のタイプのファミリベースの制約や、プルーフを消去する書き換えルールでも便利です(残念ながら)。 – dfeuer
私は多くの同様の機能を持つlibのインタフェースを再編成しようとしています。私はそれをもう少し詳しく追って、同時に表面にできるだけ触れないようにしたいと思います。 (インタフェースは、そのまま残すのが最も良いかもしれません。)私は実際には、安全でないものを使用しないという明確な答えに対して安心しています。 – Gspia