2011-04-12 12 views
7

Me he abierto paso a través de Don Stewart's Roll your own IRC bot tutorial, y estoy jugando con algunas extensiones a la misma. Mi código actual es esencialmente el mismo que "El robot monádico, con estado y con manejo de excepciones en todo su esplendor"; es demasiado largo para pegar aquí a menos que alguien lo solicite.Vuelva a conectar automáticamente una conexión de la red Haskell de una manera idiomática

Al ser un suscriptor de Comcast, es particularmente importante que el bot pueda volver a conectarse después de períodos de mala conectividad. Mi enfoque es simplemente sincronizar las solicitudes PING del servidor, y si se va sin ver un PING durante un tiempo determinado, para intentar volver a conectar.

Hasta ahora, la mejor solución que he encontrado es envolver el hGetLine en el lazo listen con System.Timeout.timeout. Sin embargo, esto parece requerir la definición de una excepción personalizada para que el catch en main pueda llamar de nuevo a main, en lugar de return(). También parece bastante frágil especificar un valor de tiempo de espera para cada individuo hGetLine.

¿Existe una solución mejor, tal vez algo que envuelve una IO a como bracket y catch para que todo el principal puede manejar los tiempos de espera de red sin el añadido de un nuevo tipo de excepción?

+1

No hay rendimiento en tiempo de ejecución de un nuevo tipo de excepción en relación con las excepciones integradas. ¿Te refieres a gastos generales de código/mantenimiento? Creo que las excepciones definidas por el usuario son buenas. De lo contrario, podría cambiar 'listen' para devolver un' Maybe() 'en tiempos de espera y coincidencia de patrones en lugar de usar excepciones. Si cambia 'Net' a' ReaderT Bot (MaybeT IO) 'puede sondear los errores de esa manera. Normalmente prefiero esto por sobre las excepciones. –

+1

No debe volver a llamar a 'main' desde un manejador de excepciones: GHC realmente debería documentar esto mejor. (Aunque, en realidad, no estoy seguro si la nueva funcionalidad 'máscara 'en GHC 7 hace que esto sea menos horrible?) Más bien, deberías fallar con algún tipo de resultado de error - un' Left' o 'Nothing' o similar - - y luego, * fuera del controlador * atrapa eso para volver a llamar a 'main'. – sclv

+0

@sclv - otro error relacionado con excepciones. Creo que las excepciones pueden ser el peor producto de CS desde GOTO. –

Respuesta

1

¿Qué tal si ejecuta una secuencia separada que realiza toda la lectura y escritura y se encarga de volver a conectar periódicamente la palanca?

Algo como esto

input :: Chan Char 
output :: Chan Char 

putChar c = writeChan output c 

keepAlive = forever $ do 
    h <- connectToServer 
    catch 
     (forever $ 
       do c <- readChan output; timeout 4000 (hPutChar h c); return()) 
     (\_ -> return()) 

La idea es encapsular toda la dificultad de volver a conectar periódicamente en un hilo separado.

+1

Esto parece ser el camino a seguir ahora que he visto cómo funcionan las excepciones asincrónicas. El tutorial de paralelismo y simultaneidad de Simon Marlow tiene una buena sección sobre estos: http://community.haskell.org/~simonmar/par-tutorial.pdf – acfoltzer

Cuestiones relacionadas