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, В любом случае вы можете найти его в содержании книги.

Другие вопросы по тегам