3

整数のこのラッパーを考えると:

newtype MyProxy a = MyProxy Int

mkProxy :: Int -> MyProxy a
mkProxy a = MyProxy a

addProxy :: MyProxy a -> MyProxy a -> MyProxy  a
addProxy (MyProxy a1) (MyProxy a2) = MyProxy $ a1+a2

以下を実行できます。

a = mkProxy 1
b = mkProxy 2
c = addProxy a b

ファントムパラメータが統一されるためです。しかし、この統合を防ぎ、 line で型エラーを発生させたいと考えていますc

ST モナドは同様の効果を達成するために rank2 型を使用します。のタイプを変更することで、おそらく同様のことができaddProxyます。しかし、私は特にこれをしたくありません。a呼び出し時に型変数が統一されないように、何らかの形で型変数に注釈を付けたいと思いaddProxyます。

これはHaskellで可能ですか?そのようなオプションが危険である理由はありますか?


編集:

部分的な解決策について詳しく説明しましょう ( が必要-XScopedTypeVariablesです)。上記のコードを次のように書き直すことができます。

c :: forall a1 a2. MyProxy a1
c = addProxy a b
    where
        a = mkProxy 1 :: MyProxy a1
        b = mkProxy 2 :: MyProxy a2

と を統合できないcためa1、これは型エラーを正しく引き起こします。a2しかし、これには 2 つの欠点がaありbます。の結果の型を明示的に指定する必要がありますmkProxy

これらの欠点を修正することは可能ですか?

4

2 に答える 2

0

これには、存在型変数が適していると思います。基本的に、独立して作成された 2 つの存在型変数は統合されません。以下testでは、2 つの の型変数を統合できないため、型チェックに失敗しますMyProxy

{-# LANGUAGE ExistentialQuantification #-}

newtype MyProxy a = MyProxy Int

data Exists f = forall a. Exists (f a)

mkProxy :: Int -> Exists MyProxy
mkProxy a = Exists (MyProxy a)

addProxy :: MyProxy a -> MyProxy a -> MyProxy a
addProxy (MyProxy a1) (MyProxy a2) = MyProxy $ a1+a2

test :: Exists MyProxy -> Exists MyProxy -> Exists MyProxy
test (Exists a) (Exists b) = Exists (addProxy a b)
于 2014-05-15T21:04:13.383 に答える