Vous n'êtes pas identifié(e).

Top posteurs

Statistiques

Partenaires

  • eXolia Hosting
  • Eggdrop.fr

#1 02/01/2012 04:19:33

Diogene
IRCzien
Lieu : Le Mans
Inscription : 09/07/2011
Messages : 179

[HASKELL] Socket IRC

Bonsoir,

En naviguant un petit peu sur la toile j'ai découvert un petit snippet, il s'agit d'une socket IRC basique rédigée en Haskell.
J'ai pensé qu'il serait bien de vous la partager.

La voici :

bot.hs

Code: Haskell
--
-- A simple, clean IRC bot in Haskell
--
--  $ ghc -O --make -o bot bot.hs
--  $ ./bot
-- or
--  $ runhaskell bot.hs
-- or
--  $ echo main | ghci bot.hs
-- or
--  $ echo main | hugs -98 bot.hs
-- or
--  $ runhugs -98 bot.hs
--
 
import Data.List
import Network
import System.IO
import System.Time
import System.Exit
import Control.Monad.Reader
-- import Control.Exception -- for base-3, with base-4 use Control.OldException
import Control.OldException
import Text.Printf
import Prelude hiding (catch)
 
server = "irc.freenode.org"
port   = 6667
chan   = "#tutbot-testing"
nick   = "tutbot"
 
--
-- The 'Net' monad, a wrapper over IO, carrying the bot's immutable state.
-- A socket and the bot's start time.
--
type Net = ReaderT Bot IO
data Bot = Bot { socket :: Handle, starttime :: ClockTime }
 
--
-- Set up actions to run on start and end, and run the main loop
--
main :: IO ()
main = bracket connect disconnect loop
  where
    disconnect = hClose . socket
    loop st    = catch (runReaderT run st) (const $ return ())
 
--
-- Connect to the server and return the initial bot state
--
connect :: IO Bot
connect = notify $ do
    t <- getClockTime
    h <- connectTo server (PortNumber (fromIntegral port))
    hSetBuffering h NoBuffering
    return (Bot h t)
  where
    notify a = bracket_
        (printf "Connecting to %s ... " server >> hFlush stdout)
        (putStrLn "done.")
        a
 
--
-- We're in the Net monad now, so we've connected successfully
-- Join a channel, and start processing commands
--
run :: Net ()
run = do
    write "NICK" nick
    write "USER" (nick++" 0 * :tutorial bot")
    write "JOIN" chan
    asks socket >>= listen
 
--
-- Process each line from the server
--
listen :: Handle -> Net ()
listen h = forever $ do
    s <- init `fmap` io (hGetLine h)
    io (putStrLn s)
    if ping s then pong s else eval (clean s)
  where
    forever a = a >> forever a
    clean     = drop 1 . dropWhile (/= ':') . drop 1
    ping x    = "PING :" `isPrefixOf` x
    pong x    = write "PONG" (':' : drop 6 x)
 
--
-- Dispatch a command
--
eval :: String -> Net ()
eval     "!uptime"             = uptime >>= privmsg
eval     "!quit"               = write "QUIT" ":Exiting" >> io (exitWith ExitSuccess)
eval x | "!id " `isPrefixOf` x = privmsg (drop 4 x)
eval     _                     = return () -- ignore everything else
 
--
-- Send a privmsg to the current chan + server
--
privmsg :: String -> Net ()
privmsg s = write "PRIVMSG" (chan ++ " :" ++ s)
 
--
-- Send a message out to the server we're currently connected to
--
write :: String -> String -> Net ()
write s t = do
    h <- asks socket
    io $ hPrintf h "%s %s\r\n" s t
    io $ printf    "> %s %s\n" s t
 
--
-- Calculate and pretty print the uptime
--
uptime :: Net String
uptime = do
    now  <- io getClockTime
    zero <- asks starttime
    return . pretty $ diffClockTimes now zero
 
--
-- Pretty print the date in '1d 9h 9m 17s' format
--
pretty :: TimeDiff -> String
pretty td = join . intersperse " " . filter (not . null) . map f $
    [(years          ,"y") ,(months `mod` 12,"m")
    ,(days   `mod` 28,"d") ,(hours  `mod` 24,"h")
    ,(mins   `mod` 60,"m") ,(secs   `mod` 60,"s")]
  where
    secs    = abs $ tdSec td  ; mins   = secs   `div` 60
    hours   = mins   `div` 60 ; days   = hours  `div` 24
    months  = days   `div` 28 ; years  = months `div` 12
    f (i,s) | i == 0    = []
            | otherwise = show i ++ s
 
--
-- Convenience.
--
io :: IO a -> Net a
io = liftIO

Source : http://www.haskell.org/haskellwiki/Roll … bot/Source

Cordialement, Diogene.


Mieux vaut mourir incompris que passer sa vie à s'expliquer. [William Shakespeare]

Bon, c'est Diogene, mais c'est un humain malgré tout [CrazyCat]

Hors ligne

#2 02/01/2012 09:49:52

Darks
IRCzien
Inscription : 04/07/2011
Messages : 122

Re : [HASKELL] Socket IRC

La syntaxe est simplissime... Belle découverte.

Hors ligne

#3 27/02/2012 11:53:56

iZy
Nouveau IRCzien
Inscription : 27/08/2011
Messages : 17

Re : [HASKELL] Socket IRC

CECI est certainement l'un des langages les plus puissants qui existent à l'heure actuelle.

Fut un temps je pratiquais régulièrement les langages communs (C, Perl, Python et autre joyeusetés procédurales), mais ce langage à révolutionné ma vision de la programmation !

Je me permets donc de relancer ce petit topic en vous fournissant différentes informations histoire de convaincre les plus courageux de plonger dans la beauté du lambda calcul

Haskell est un langage FORTEMENT TYPÉ. Ici, les types ont beaucoup d'importance comme en CAML (pour ceux qui en ont fait), car ils permettent au compilateur/interpréteur de raisonner (réellement !) sur votre programme, et de ne pas le "lire bêtement" (si j'ose dire) comme un compilateur C par exemple. Ainsi, un programme Haskell "compile beaucoup moins souvent" qu'un autre langage car on fait souvent des erreurs de types. Cependant, cela permet de déceler A LA COMPILATION des erreurs qui ne seraient, dans d'autre langages, décelables qu'A l'EXECUTION (voila pourquoi, contrairement à ailleurs, on peut être CERTAIN à 100% qu'un programme Haskell ne contient AUCUN bug).

D'autre part, Haskell est le seul langage que je connaisse qui soit paresseux : c'est à dire qu'il ne fait que ce dont il a réellement besoin, et pas ce que le programmeur lui dit de faire. Un petit exemple : à supposer que vous ayez besoin du minimum d'une liste. Eh bien, vous pouvez déterminer ce minimum en triant totalement la liste, puis en récupérant le premier élément. Ainsi, comme haskell n'aura besoin que du premier élément, il ne triera que partiellement la liste (en fait il se contentera de prendre le plus petit : le minimum).

Tout cela pour dire que Haskell permet de faire des codes SÛRS (bien plus qu'en PERL par exemple), CONCIS (50 lignes représentent déjà un programme assez complexe, réalisable en plusieurs centaines de lignes de C), et CLAIR (car le style de programmation fonctionnel est infiniment plus intuitif que le style procédural).

Une dernière petite remarque : haskell est l'un des seuls langages que je connaisse où on passe plus de temps à réfléchir qu'à écrire. Chaque ligne nécessite une réflexion assez conséquente, et on ne produit pas du code à la même vitesse qu'en PHP. Cependant, puisque le résultat est le même, autant écrire moins et réfléchir plus, vous ne trouvez pas ?

Pour les curieux que ça pourrait interesser, voila un tutoriel traduit en français
http://lyah.haskell.fr/


i love mankind ; it's people i can't stand
[Charles M. Schulz]

Hors ligne

Pied de page des forums

435930 visites ( 128 aujourd'hui ) 3 visiteurs en ligne
Copyright © 2004 - 2013 IRCz