2017-12-15 10 views
0

メソッドを持たない2つのクラスを用意しましょう。もう1つはサブクラスです。 さらに、タイプがunsafeCoerceの関数f5f6を想定します。余分な関数の制約を取り除くにはどうすればよいですか?

ghciは、これらの関数を構成し、ScopedTypeVariablesの助けを借りてシグネチャを見つけることができます(f56, f56b and f56'を参照)。 これらは基本的に制約Hmmを持つ関数です。

  1. それはそれは、制約の中でクラスSHmmを参照 せずにそれを書くされ、f56cを書くことは可能ですか?例えば。いくつかの言語プラグマの助けを借りてこの をghciでコンパイルできますか?

  2. クラスにメソッドがない場合、unsafeCoerceを使用するとどんな危険がありますか? (またはサブクラスSHmm にはメソッドがありません) への他の方法/推奨方法はありますかf5f6?それだけでf56 = f5 . f6を書き込むことはできませんので、なぜf5f6次のコードで

そして最後の一つとしては、自分の署名を持っていますか? (特に場合はSHmmf56を書くときにその制約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 
+1

「安全でない」ものに魅力を感じるのはなぜですか?実際に何を達成しようとしていますか? – chi

+1

他の人が言っているように、これは本当に意味をなさないものです。あなたは 'Data.Coerce'で' Coercible'疑似クラスをチェックするのが面白いかもしれません。それはいくつかのかなり強力な強制的な機械です。 'Data.Type.Coercion'でそれを扱うためのツールがいくつかあります。 'coerce'関連の書き換えルールにも注意してください。 'containers'パッケージには、私が数年前に書いた良い例がいくつかあります。安全ではない強制変換は、(ある種のタイプのファミリベースの制約や、プルーフを消去する書き換えルールでも便利です(残念ながら)。 – dfeuer

+0

私は多くの同様の機能を持つlibのインタフェースを再編成しようとしています。私はそれをもう少し詳しく追って、同時に表面にできるだけ触れないようにしたいと思います。 (インタフェースは、そのまま残すのが最も良いかもしれません。)私は実際には、安全でないものを使用しないという明確な答えに対して安心しています。 – Gspia

答えて

5

これは絶対にないの安全な使用ですunsafeCoerce。基本的に、f5は、それぞれが特定のクラスのインスタンスを持っていれば、任意の2つのタイプを互いにシグネチャで変換できます。しかし、それがの間のタイプmm1の間の関係について何も教えてくれないことを知っています。それが効果的にちょうど

f5 :: (m1 ~ Int, m ~ Int) => m -> m1 

別名

f5 :: Int -> Int 
f5 = unsafeCoerce 

になり、その後ので–が言うHmmインスタンスを持つ一種類のみ、Int –がある場合、これは安全であることができる唯一の方法はある...それはです明らかに非常に有用ではないにもかかわらず、実際に動作することが保証されています。しかし、他のインスタンス、たとえばSHmm Stringを追加するとすぐに、IntStringの間の完全な偽“変換関数”が得られます。それは(すべてのこれらの機能は安全でなく、完全に不合理である場合には)Voidと同型のみのタイプが今まで満たすことができる方法でない限り、クラスHmmSHmmは、任意のメソッドを持っているかどうか

は、ここでは関係ありません。

だから、f5f6は最初からうまくいきませんので、私は残りの部分に何に答えるべきか分かりません。私は概念的なレベルでさえこのことがどういう意味があるのか​​見当たりません。

+0

これは、1つのパスを閉じるのに役立ちます。私はまだ「機能セットを分類する」さまざまな方法を試みています(あなたは数日前にq関連しています)。 – Gspia

関連する問題