我想将字段sType的数据类型表示为SType(来自zeromq-haskell)的实例的任何东西。 SType是zeromq套接字类型。在zeromq-哈斯克尔源的一个例子是这样的:Haskell数据字段作为类型类的一个实例
data Pair = Pair
instance SType Pair where
zmqSocketType = const pair
这就是我现在得到
data SocketOpts = SocketOpts
{ end :: SocketEnd
, sType :: SType st => st
}
但是当我使用它像这样socket ctx $ sType so
我得到:
Ambiguous type variable `a0' in the constraint:
(SType a0) arising from a use of `sType'
(插座的签名是socket :: SType a => Context -> a -> IO (Socket a)
当我尝试创建一个SocketOpt S IN ghci中,我得到:
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
我从此明白的是,S型是更普遍的是我自找的(拉,这是S型的实例)。我应该如何表达我想要的东西?
编辑
此:
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