2011-12-29 9 views
1

フィールドsTypeを持つデータ型を、(zeromq-haskellの)STypeのインスタンスであるものとして表現したいと思います。 STypeはzeromqソケットタイプです。Haskell typeclassのインスタンスとしてのデータフィールド

Ambiguous type variable `a0' in the constraint: 
(SType a0) arising from a use of `sType' 

data Pair = Pair 
instance SType Pair where 
    zmqSocketType = const pair 

ここで私は今

data SocketOpts = SocketOpts 
{ end :: SocketEnd 
, sType :: SType st => st 
} 

を持っているしかし、私はそうsocket ctx $ sType soのようにそれを使用するときに私が得るものです:zeromq-Haskellのソースでは1例がこれです(ソケットの署名はsocket :: SType a => Context -> a -> IO (Socket a)

私はSocketOpt GHCiの中のSは、私が手:私はこのことから理解することはSTYPEは、私が求めてきたもの(STYPEのインスタンスである、プル)ことがより一般的であるということです

let so = SocketOpts (Bind "some") Pull 

<interactive>:1:35: 
Could not deduce (st ~ Pull) 
from the context (SType st) 
    bound by a type expected by the context: SType st => st 
    at <interactive>:1:10-38 
    `st' is a rigid type variable bound by 
     a type expected by the context: SType st => st 
     at <interactive>:1:10 
In the second argument of `SocketOpts', namely `Pull' 
In the expression: SocketOpts (Bind "some") Pull 
In an equation for `so': so = SocketOpts (Bind "some") Pull 

。私はここで何をしたいのですか?


編集

この:と一緒に使用されている

data SocketOpts st = SocketOpts 
    { end :: SocketEnd 
    , sType :: st 
    } 

zmqSource :: (ResourceIO m, SType st) => Context -> SocketOpts st -> Source m a 
zmqSource ctx so = sourceIO 
      mkSocket 
      recvSock 
      (\x -> undefined) 
      where 
       recvSock = undefined 
       mkSocket = socket ctx $ sType so 

が動作しているようだが、私は中に未解決の問題を残しておきます場合は、これを行うよりエレガントな方法がありますか?


編集2

みんな、あなたの答えに心より感謝申し上げます。あなたのフィードバックに基づいて、私は今(それはgithubの上で読みやすいですと、私はここに掲載しません)、次の

https://github.com/boothead/zeromq-conduit/blob/master/Data/Conduit/ZMQ.hs

を持っている私が試してみて、表現するためにGADTを(と思う)使用しました通常のソケットとSubソケットの設定の違いですが、現時点ではシワがあります:SockOptsタイプを使用してサブソケットを設定することができます。サブスクリプションは呼び出されず、動作しません。

SockOpts (Connect "tcp://127.0.0.1:9999") Sub -- This would be bad 

これを禁止するようにタイプシステムを取得する方法はありますか。山括弧に入っているもののようなもの?

SockOpts :: (SType st, <not SubsType st>) => SocketEnd -> st -> SocketOpts st 

答えて

0

GADTを送信しましたか?

data SocketOpts where 
    SocketOpts :: SType st => SocketEnd -> st -> SocketOpts 

またexistentialsでGADTsを試すことができます。

data SocketOpts where 
    SocketOpts :: SocketEnd -> (forall st . SType st => st) -> SocketOpts 
3

私はzeromq-から(STYPEのインスタンスであるものであることをフィールドSTYPEとデータ型を表現したいのですがhaskell)。

ここで「何か」の意味には多少の曖昧さがあります。

SocketOptsの値をパラメトリックタイプで作成し、SocketOptsの値を使用すると、STypeインスタンスの要件を適用しますか?次に、通常のパラメータ化された型は、あなたの編集のようにうまくいきます。

SocketOptsの値に指定された型のインスタンスが含まれ、値が使用されるのではなく作成されたときに制約が適用されるようにしますか?そして、GADT定義は動作します:

data SocketOpts st where 
    SocketOpts :: (SType st) => SocketEnd -> st -> SocketOpts st 

あなたが特定のタイプによって、それをパラメータ化することなく、への任意のインスタンスは、SocketOpts値を作成使用しますか?

data SocketOpts where 
    SocketOpts :: (SType st) => SocketEnd -> st -> SocketOpts 

を...しかしexistentialsは厄介なことができ、そしてそれはあなたがこのような何かを行うことができ、すべてがSocketOpts上のパターンマッチで、その後SType用に定義されたメソッドを使用することを警告する:それは実存タイプが動作するのです。特定のタイプの知識は失われます。

SocketOptsの値を使用して特定のタイプを作成することを諦めて、最後に任意のインスタンスを選択しますか?それは普遍的な定量型です:

data SocketOpts where 
    SocketOpts :: SocketEnd -> (forall st. SType st => st) -> SocketOpts 

...私はあなたの元のバージョンがあったと信じています。この場合、単相性値を使用してSocketOpts値を作成することはできません。多形値のみを使用することはできません。Intの値11と数値リテラル11 :: Num a => aの違いを考慮してください。この場合、GHCはまだ選択するインスタンスを知る必要があるので、SocketOptsの内容を使用する場合は、STypeメソッドを使用する前に特定のタイプが必要であることに注意してください。

両方とも見たエラーは、普遍的な定量化されたタイプに関する上記の警告に由来しています:STypeインスタンスを選択する必要がある何かをGHCに十分な情報を与えずに適用したため "あいまい型" "エラーは、単相性値を持つSocketOptsを作成しようとしたためです。

私は存在バージョンがあなたが試していたものと思われます。しかし、STypeの異なるインスタンスを混ぜるべき魅力的な理由がない限り、パラメトリックGADTがおそらく良い選択です。

関連する問題