[Haskell-cafe] MaybeT, guards and run-time pattern matching failure

Joel Reymont joelr1 at gmail.com
Tue Nov 1 07:50:09 EST 2005


I'm trying to optimize this and I thought that things that return  
Nothing in the Maybe monad should fail the whole computation  
sequence. Something subtle is going wrong, I think. MaybeT is at the  
end of this message.

----
timeout :: forall a.Int -> IO a -> IO (Maybe a)
connect_ :: HostName -> Int -> IO Handle
startSSL :: IO (SSL, BIO, BIO)

type EngineState = MaybeT (WriterT [Log] (StateT World IO))

connect :: [Prop] -> HostName -> Int -> EngineState ()
connect env h p =
     do h <- liftIO $ timeout 0 $ connect_ h p -- no complains about  
this
        (ssl', tob, fromb) <- liftIO $ timeout 0 startSSL -- bummer,  
see below

./Script/Engine.hs:101:7:
     Couldn't match `Maybe (SSL, BIO, BIO)' against `(a, b, c)'
       Expected type: Maybe (SSL, BIO, BIO)
       Inferred type: (a, b, c)
     When checking the pattern: (ssl', tob, fromb)
     In a 'do' expression: (ssl', tob, fromb) <- liftIO $ (timeout 0  
startSSL)
----

I thought I would change it like this:

----
connect env h p =
     do (Just h) <- liftIO $ timeout 0 $ connect_ h p -- no complains  
about this
----

but when the connection times out (i'm making it with a delay of 0) I  
get the following runtime error:

*** Exception: Pattern match failure in do expression at ./Script/ 
Engine.hs:103:

So am I stuck with this?

----
connect :: [Prop] -> HostName -> Int -> EngineState ()
connect env h p =
     do m'h <- liftIO $ timeout 0 $ connect_ h p
        m'ssl <- liftIO $ timeout 0 startSSL
        guard (m'h /= Nothing && m'ssl /= Nothing) -- do I need this?!
        let h = case m'h of (Just h) -> h
        let (ssl', tob, fromb) = case m'ssl of a -> a
----

And this is MaybeT:

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

instance (Monad m) => Monad (MaybeT m) where
     (MaybeT mon) >>= f =
         MaybeT (mon >>= maybe (return Nothing) (runMaybeT . f))
     return              = MaybeT . return . Just

instance MonadTrans MaybeT where
     lift mon = MaybeT (mon >>= return . Just)

instance (Monad m) => MonadPlus (MaybeT m) where
     mzero                       = MaybeT (return Nothing)
     mplus (MaybeT a) (MaybeT b) = MaybeT $ do
         ma <- a
         mb <- b
         return $ ma `mplus` mb

instance MonadState s m => MonadState s (MaybeT m) where
     get = lift get
     put s = lift $ put s

instance (MonadIO m) => MonadIO (MaybeT m) where
     liftIO = lift . liftIO

     Thanks, Joel

--
http://wagerlabs.com/







More information about the Haskell-Cafe mailing list