Haskell 网络套接字 header
Haskell websockets header
我正在尝试阅读 haskell 中的 websockets header。
当前代码如下
import Network
import Network.Socket.Internal
import Text.Printf
import Control.Monad
import Control.Monad.IO.Class
import Data.Maybe
import Data.List
import Data.Digest.Pure.SHA (bytestringDigest, sha1)
import Text.Regex
import System.IO
port :: Int
port = 8080
bufferLength :: Int
bufferLength = 2048
keyRegex :: String
keyRegex = "Sec-WebSocket-Key: (.+)(\r)"
response :: String
response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nsec-websocket-accept: changethis\r\n\r\n"
guidString :: String
guidString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
talk :: MonadIO m => Handle -> m String
talk handle = do liftIO $ hGetContents handle
main :: IO()
main = withSocketsDo $ do
sock <- listenOn (PortNumber (fromIntegral port))
printf "Listening on port %d\n" port
forever $ do
(handle, host, port) <- accept sock
printf "Accepted connection from %s: %s\n" host (show port)
hSetBuffering handle NoBuffering
putStrLn $ talk handle
代码抛出错误
Main.hs:38:16:
Couldn't match type `[Char]' with `Char'
Expected type: String
Actual type: [String]
In the return type of a call of `talk'
In the second argument of `($)', namely `talk handle'
In a stmt of a 'do' block: putStrLn $ talk handle
如何打印header字符串? Talk 函数应该获取 header 字符串并 return 它被打印出来。
Return talk handle
的类型是 (MonadIO m => m String)
。
putStrLn
的类型为 String -> IO ()
或 [Char] -> IO ()
.
[]
是一个单子。
putStrLn
需要一个字符列表,但它得到的值是 (MonadIO m => m String)
.
m
变成一个列表,putStrLn
得到一个 [String]
类型的值,这是错误的。
正如@Zeta 建议的那样,使用 talk handle >>= putStrLn
代替:
>>=
是允许使用另一次计算的结果继续计算的运算符。在你的情况下,你可以阅读 talk handle >>= putStrLn
如下:
talk handle -- first compute it
>>= putStrLn -- then take string from result of `talk handle` and print it
不会有任何像 putStrLn $ talk handle
:
这样的错误
(>>=) :: Monad m => m a -> (a -> m b) -> m b
talk handle :: MonadIO m => m String
(>>=) (talk handle) :: MonadIO m => (String -> m b) -> m b
putStrLn :: String -> IO ()
(>>=) (talk handle) putStrLn :: IO () -- `m` becomes `IO`
已编辑:
在这里你可以找到 IO
monad 的介绍:LYHFGG, Input and Output
在这里您可以找到对 monad 的一般介绍:LYHFGG, A Fistful of Monads。
您应该了解 Functor
和 Applicative
才能阅读 A Fistful of Monads
。无论如何你都可以在书的内容中找到它。
我正在尝试阅读 haskell 中的 websockets header。
当前代码如下
import Network
import Network.Socket.Internal
import Text.Printf
import Control.Monad
import Control.Monad.IO.Class
import Data.Maybe
import Data.List
import Data.Digest.Pure.SHA (bytestringDigest, sha1)
import Text.Regex
import System.IO
port :: Int
port = 8080
bufferLength :: Int
bufferLength = 2048
keyRegex :: String
keyRegex = "Sec-WebSocket-Key: (.+)(\r)"
response :: String
response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nsec-websocket-accept: changethis\r\n\r\n"
guidString :: String
guidString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
talk :: MonadIO m => Handle -> m String
talk handle = do liftIO $ hGetContents handle
main :: IO()
main = withSocketsDo $ do
sock <- listenOn (PortNumber (fromIntegral port))
printf "Listening on port %d\n" port
forever $ do
(handle, host, port) <- accept sock
printf "Accepted connection from %s: %s\n" host (show port)
hSetBuffering handle NoBuffering
putStrLn $ talk handle
代码抛出错误
Main.hs:38:16:
Couldn't match type `[Char]' with `Char'
Expected type: String
Actual type: [String]
In the return type of a call of `talk'
In the second argument of `($)', namely `talk handle'
In a stmt of a 'do' block: putStrLn $ talk handle
如何打印header字符串? Talk 函数应该获取 header 字符串并 return 它被打印出来。
Return talk handle
的类型是 (MonadIO m => m String)
。
putStrLn
的类型为 String -> IO ()
或 [Char] -> IO ()
.
[]
是一个单子。
putStrLn
需要一个字符列表,但它得到的值是 (MonadIO m => m String)
.
m
变成一个列表,putStrLn
得到一个 [String]
类型的值,这是错误的。
正如@Zeta 建议的那样,使用 talk handle >>= putStrLn
代替:
>>=
是允许使用另一次计算的结果继续计算的运算符。在你的情况下,你可以阅读 talk handle >>= putStrLn
如下:
talk handle -- first compute it
>>= putStrLn -- then take string from result of `talk handle` and print it
不会有任何像 putStrLn $ talk handle
:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
talk handle :: MonadIO m => m String
(>>=) (talk handle) :: MonadIO m => (String -> m b) -> m b
putStrLn :: String -> IO ()
(>>=) (talk handle) putStrLn :: IO () -- `m` becomes `IO`
已编辑:
在这里你可以找到 IO
monad 的介绍:LYHFGG, Input and Output
在这里您可以找到对 monad 的一般介绍:LYHFGG, A Fistful of Monads。
您应该了解 Functor
和 Applicative
才能阅读 A Fistful of Monads
。无论如何你都可以在书的内容中找到它。