Haskell websockets header
Я пытаюсь прочитать заголовок websockets в haskell.
Текущий код выглядит следующим образом
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
Как напечатать строку заголовка? Функция Talk должна получить строку заголовка и вернуть ее для печати.
1 ответ
Тип возврата 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
монада: LYHFGG, вход и выход
Здесь вы можете найти введение в монады в целом: LYHFGG, Горсть монад.
Вы должны знать о Functor
а также Applicative
чтобы читать A Fistful of Monads
, В любом случае вы можете найти его в содержании книги.