我在haskell写一个聊天服务器。早些时候我有tcp套接字。现在我转向WebSockets。我想在它上面创建一个NetworkConn
的瘦包装..我在编写accept
函数时遇到了问题。
acceptReuqest PendingConnection
返回Connection
和
fst <$> accept Socket
是Socket
。
所以,我试过跟随..
为NetworkConn
Socket, Connection, PendingConnection
class NetworkConn sock where
accept :: (NetworkConn myconn) => sock -> IO myconn
instance NetworkConn NS.Socket where
accept sock = fst <$> NS.accept sock
instance NetworkConn WS.Connection where
accept sock = error "Not allowed"
acceptReuqest PendingConnection
返回Connection
instance NetworkConn WS.PendingConnection where
accept sock = WS.acceptRequest sock
这给我NS.Socket
中的错误
Couldn't match type ‘myconn’ with ‘NS.Socket’
‘myconn’ is a rigid type variable bound by
the type signature for
acceptC :: NetworkConn myconn => NS.Socket -> IO myconn
at src/HChat/Network.hs:21:3
Expected type: IO
(myconn, network-2.6.2.1:Network.Socket.Types.SockAddr)
Actual type: IO
(NS.Socket, network-2.6.2.1:Network.Socket.Types.SockAddr)
Relevant bindings include
acceptC :: NS.Socket -> IO myconn
(bound at src/HChat/Network.hs:21:3)
In the second argument of ‘(<$>)’, namely ‘NS.accept sock’
In the expression: fst <$> NS.accept sock
和
Couldn't match type ‘myconn’ with ‘WS.Connection’
‘myconn’ is a rigid type variable bound by
the type signature for
acceptC :: NetworkConn myconn => WS.PendingConnection -> IO myconn
at src/HChat/Network.hs:31:3
Expected type: IO myconn
Actual type: IO WS.Connection
Relevant bindings include
acceptC :: WS.PendingConnection -> IO myconn
(bound at src/HChat/Network.hs:31:3)
我开始阅读class
并且无法理解为什么会出现错误。
我想这是一个语法错误,但无法弄清楚。请帮忙。
是否可以将返回类型限制为NetworkConn,因为我只想调用仅在NetworkConn中定义的几个方法。?
尝试两个课程:
class CandidateConn c where
acceptC :: (NetworkConn s) => c -> IO s
class NetworkConn sock where
send :: sock -> C.ByteString -> IO ()
recv :: sock -> IO C.ByteString
accept :: (CandidateConn conn) => conn -> IO sock
instance NetworkConn NS.Socket where
send sock text = void $ NSB.send sock text
recv sock = NSB.recv sock 1024
accept c = acceptC c
instance CandidateConn NS.Socket where
acceptC sock = fst <$> NS.accept sock
给出:
Couldn't match type ‘s’ with ‘NS.Socket’
‘s’ is a rigid type variable bound by
the type signature for
acceptC :: NetworkConn s => NS.Socket -> IO s
at src/HChat/Network.hs:29:3
Expected type: IO
(s, network-2.6.2.1:Network.Socket.Types.SockAddr)
Actual type: IO
(NS.Socket, network-2.6.2.1:Network.Socket.Types.SockAddr)
Relevant bindings include
acceptC :: NS.Socket -> IO s (bound at src/HChat/Network.hs:29:3)
答案 0 :(得分:3)
此类型签名:
class NetworkConn sock where
accept :: (NetworkConn myconn) => sock -> IO myconn
说,“作为sock
的{{1}}类型提供了一个函数NetworkConn
,它接受accept
并返回一个操作,从而产生调用者所需的任何类型,如只要该类型依次为sock
。“
这是你不能坚持的承诺。你可能想写一下它返回“某些特定于NetworkConn
的类型,它也实现了sock
”。这就是相关类型的用途。
粗略地说,您启用了TypeFamilies扩展,然后编写
NetworkConn
除此之外缺少class NetworkConn sock where
type AcceptedConn sock :: *
accept :: sock -> IO (AcceptedConn sock)
的{{1}}约束。我很难找到正确的语法来表达这一点,目前无法进行语法检查,但你可以试试这个:
NetworkConn
我认为这需要启用FlexibleInstances。
然后,实例声明变为:
AcceptedConn
正如我所说,我根本没有对此进行语法检查。
答案 1 :(得分:1)
怎么样
class NetworkConn sock where
accept :: sock -> IO sock
你写的是一个通用的返回类型,而我认为你的accept
方法只返回特定的连接类型。
如果您确实需要动态返回,则可能需要2个类型类,如
class CandidateConn sock where
-- some methods
class NetworkConn sock where
accept :: CandidateConn c => c -> IO sock
答案 2 :(得分:1)
#haskell irc频道的高贵灵魂{As}
建议使用https://wiki.haskell.org/Multi-parameter_type_class
它有效..谢谢{As}
{-# LANGUAGE MultiParamTypeClasses #-}
module HChat.Network where
-- For Network.Socket library
import qualified Network.Socket as NS (Socket, accept)
import qualified Network.Socket.ByteString as NSB (send, recv)
import qualified Data.ByteString.Char8 as C
-- For WebSockets library
import qualified Network.WebSockets as WS
import Control.Monad (void)
class NetworkConn sock conn where
send :: conn -> C.ByteString -> IO ()
recv :: conn -> IO C.ByteString
accept :: sock -> IO conn
instance NetworkConn NS.Socket NS.Socket where
send conn text = void $ NSB.send conn text
recv conn = NSB.recv conn 1024
accept sock = fst <$> NS.accept sock
instance NetworkConn WS.PendingConnection WS.Connection where
send sock text = WS.sendTextData sock text
recv sock = WS.receiveData sock
accept sock = WS.acceptRequest sock