2016-03-27 6 views
1
type Foo = { 
    x :: Int, 
    y :: Int 
} 

type Bar = { 
    x :: Int 
} 

foo :: Foo 
foo = {x:1,y:2} 
bar :: Bar 
bar = foo 

はタイプunsafeCoerceなしでサブレコードを取得する方法はありますか?

を(一致しませんでした)

タイプ

(Y ::のInt )

でなぜこれが可能ではないでしょうか?

私は

type Bar a = { 
    x :: Int | a 
} 

を使用することはできませんし、レコード

bar = {x : foo.x} 

ですunsafeCoerceのみのオプションを再作成したくありませんか?

unsafeCoerceの使用にはどのような問題がありますか?

答えて

3

あなたは関数を作成する場合にのみ、あなたは代わりに開い行を使用することができ、いくつかの特定のフィールドを持つレコードを扱う:

bar :: forall r. { x :: Int | r } -> { x :: Int | r } 
bar rec = rec 

まだ両方FooBar同義語と互換性があります。

しかし、それはどちらかは良いしませんし、あなたがしかない再びBarFooを強制、および、約yその後、unsafeCoerceがいる限り、使用しても大丈夫であるべき「忘れる」したいだけならば。

私は強くunsafeCoerceエイリアシング直接ではなく、しかし、それを使用してお勧めします:

forget :: Foo -> Bar 
forget = Unsafe.Coerce.unsafeCoerce 

それはあなたが原則に基づいた方法でそれを使用していると思う場合でも、それを直接使用しているとき間違いを犯すのは簡単です。

個人的には、定型文が含まれていても、フィールドがなくても新しいレコードを作成できます。

+0

'bar = foo :: Bar'を使用できない、または実装されていない理由はありますか? – ais

+0

簡単な答えは、タイプシステムがそのように動作することを望まないということです。なぜなら、いくつかの哲学的な理由がありますが、ここでは非常に具体的なものがあります:もしあなたがそれを行うことができれば、あなたは安全でないタイプからの影響を消滅させることもできます。 –

+0

しかし、新しいレコード '{x:foo.x}'を作成することで既にそれを行うことができます。 'a :: B'は' {x:a.x、y:b.y、...} 'に変換することができます。 – ais

関連する問題