Guest User

Untitled

a guest
Jun 19th, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {----------------------------------------------------------------------------
  2.  
  3. Компилировать:
  4.     ghc -O -threaded fact.hs
  5.  
  6. Использовать:
  7.     $ ./fact server 12345 &
  8.     Listening on 12345
  9.    
  10.     $ ./fact client ::1 12345
  11.     345345435435
  12.     Answer := [3,5,7,11,13,13,59,157,191]
  13.     -5.3
  14.     Answer := NaN
  15.     43534524542534543534
  16.     Answer := [2,485777,1495631,29960041]
  17.  
  18. Фичи:
  19.     + Разбор параметров командной строки
  20.     + Обработка некорректных данных
  21.     + Клиент-серверная архитектура
  22.     + Полностью асинхронный многопоточный tcp-сервер
  23.     + Распараллелизация алгоритмов "из коробки"
  24.     + Поддержка Unicode, IPv6 и BigInteger сразу "из коробки"
  25.     + Как следствие, мгновенный отклик в любой ситуации
  26.     + Мемоизация списка простых чисел (благодаря ленивости)
  27.     ! Производительность на уровне чистого Си
  28.     + Полная кроссплатформенность (Windows, *nix, Mac OS X, etc.)
  29.     + Исходник чуть больше 60 строк (используются стандартные библиотеки)
  30.     + Код фактически не нуждается в комментариях
  31.     + Правильность тривиально доказывается мат. аппаратом прямо по коду с помощью индукции
  32.     ! Время разработки с нуля чуть меньше 30 минут
  33.  
  34. А теперь сравните с этим уродливым (взято из доков по boost)
  35.  
  36.     class server
  37.     {
  38.     public:
  39.       server(boost::asio::io_service& io_service, short port)
  40.         : io_service_(io_service),
  41.           acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
  42.       {
  43.         session* new_session = new session(io_service_);
  44.         acceptor_.async_accept(new_session->socket(),
  45.             boost::bind(&server::handle_accept, this, new_session,
  46.               boost::asio::placeholders::error));
  47.       }
  48.     .........
  49.  
  50. Haskell. Feel the difference.
  51.  
  52. ----------------------------------------------------------------------------}
  53.  
  54.  
  55. import Network (listenOn, withSocketsDo, accept, connectTo, PortID(..), Socket)
  56. import System (getArgs)
  57. import System.IO (hSetBuffering, hGetLine, hPutStrLn, BufferMode(..), Handle)
  58. import Control.Concurrent (forkIO)
  59.  
  60. main :: IO ()
  61. main = do
  62.     args <- getArgs
  63.     case args of
  64.         ["server", port] -> server port
  65.         ["client", host, port] -> client host port
  66.         otherwise -> error "Usage: fact server [port] | fact client [host] [port]"
  67.  
  68. getPort :: String -> PortID
  69. getPort port = PortNumber $ fromIntegral (read port :: Int)  
  70.  
  71. -- client part
  72.  
  73. client :: String -> String -> IO ()
  74. client host port = withSocketsDo $ do
  75.     handle <- connectTo host $ getPort port
  76.     hSetBuffering handle NoBuffering
  77.     repl handle
  78.    
  79. repl :: Handle -> IO ()
  80. repl handle = do
  81.     getLine >>= hPutStrLn handle
  82.     putStr "Answer := "
  83.     hGetLine handle >>= putStrLn
  84.     repl handle
  85.    
  86. -- server part
  87.  
  88. server :: String -> IO ()
  89. server port = withSocketsDo $ do
  90.     sock <- listenOn $ getPort port
  91.     putStrLn $ "Listening on " ++ port
  92.     sockHandler sock
  93.  
  94. sockHandler :: Socket -> IO ()
  95. sockHandler sock = do
  96.     (handle, _, _) <- accept sock
  97.     hSetBuffering handle NoBuffering
  98.     forkIO $ processRequest handle
  99.     sockHandler sock
  100.  
  101. processRequest :: Handle -> IO ()
  102. processRequest handle = do
  103.     line <- hGetLine handle
  104.     hPutStrLn handle $ prettyPrint $ reads line
  105.     processRequest handle
  106.  
  107. prettyPrint :: [(Integer, String)] -> String
  108. prettyPrint [(number, _)] = show $ primeFactors number
  109. prettyPrint []            = "NaN"
  110.  
  111. primes = 2 : sieve [3, 5..] where
  112.     sieve (p:xs) = p : sieve [x | x <- xs, rem x p /= 0]
  113.  
  114. primeFactors :: Integer -> [Integer]
  115. primeFactors n = factor primes n where
  116.     factor ps@(p:pt) n | p*p > n      = [n]
  117.                        | rem n p == 0 = p : factor ps (quot n p)
  118.                        | otherwise    = factor pt n
Add Comment
Please, Sign In to add comment