On Wed, Feb 11, 2015 at 05:21:20PM +0100, 'Aditya Bhimanavajjula' via 
ganeti-devel wrote:
From: BSRK Aditya <[email protected]>


Signed-off-by: BSRK Aditya <[email protected]>
---
cabal/ganeti.template.cabal     |    2 +-
src/Ganeti/BasicTypes.hs        |   18 +++++++++---------
src/Ganeti/Logging/WriterLog.hs |   17 ++++++++---------
src/Ganeti/THH/HsRPC.hs         |    9 ++++-----
src/Ganeti/WConfd/Monad.hs      |   11 +++++------
5 files changed, 27 insertions(+), 30 deletions(-)

diff --git a/cabal/ganeti.template.cabal b/cabal/ganeti.template.cabal
index 9067b51..07c435f 100644
--- a/cabal/ganeti.template.cabal
+++ b/cabal/ganeti.template.cabal
@@ -59,7 +59,7 @@ library
    , json                          >= 0.5        && < 0.9
    , lens                          >= 3.10       && < 4.4
    , lifted-base                   >= 0.2.0.3    && < 0.3
-    , monad-control                 >= 0.3.1.3    && < 0.4
+    , monad-control                 >= 1.0.0.1

We should keep compatibility with older versions as well. Therefore the lower bound should be kept the same. Then it'll necessary to investigate in which version exactly the interface in monad-control has changed and use the CPP extension in the appropriate modules to provide the correct implementation based on the version. For an example see https://groups.google.com/d/msg/ganeti-devel/oZmFXBFgzRE/8rZTwv9pW4MJ

Also it's a good practise to always keep the upper bound, because it's possible that a next major version of the library will change and suddenly things will break unexpectedly. I'd suggest to put the upper bound to "< 1.1".

(If the upper bound is too strict, it's easy to raise it, and users get a meaningful error message that cabal can't find the required version of a library. On the other handm if the upper bound is too loose and the library changes, users might get a lot of compiler errors they don't understand.)

    , MonadCatchIO-transformers     >= 0.3.0.0    && < 0.4
    , network                       >= 2.3.0.13   && < 2.7
    , parallel                      >= 3.2.0.2    && < 3.3
diff --git a/src/Ganeti/BasicTypes.hs b/src/Ganeti/BasicTypes.hs
index fb57d1a..8e08347 100644
--- a/src/Ganeti/BasicTypes.hs
+++ b/src/Ganeti/BasicTypes.hs
@@ -3,6 +3,7 @@
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE UndecidableInstances #-}

Is UndecidableInstances needed by the instances for new monad-control library? Isn't there a way around it? The extension is potentially dangerous - it can do nasty things to the compiler, and also masks a lot of checks.

If we need to keep it, I'd probably document the places that require it, prehaps adding a comment like "-- needs UndecidableInstances" or something to each instance declaration that needs it.

We might also try to ask on haskell-cafe or the maintainer, if the library is supposed to be used with the extension.


{-

@@ -200,18 +201,18 @@ instance (MonadBase IO m, Error a) => MonadBase IO 
(ResultT a m) where
                   . (try :: IO a -> IO (Either IOError a))

instance (Error a) => MonadTransControl (ResultT a) where
-  newtype StT (ResultT a) b = StResultT { runStResultT :: GenericResult a b }
-  liftWith f = ResultT . liftM return $ f (liftM StResultT . runResultT)
-  restoreT = ResultT . liftM runStResultT
+  type StT (ResultT a) b = GenericResult a b
+  liftWith f = ResultT . liftM return $ f runResultT
+  restoreT = ResultT
  {-# INLINE liftWith #-}
  {-# INLINE restoreT #-}

instance (Error a, MonadBaseControl IO m)
         => MonadBaseControl IO (ResultT a m) where
-  newtype StM (ResultT a m) b
-    = StMResultT { runStMResultT :: ComposeSt (ResultT a) m b }
-  liftBaseWith = defaultLiftBaseWith StMResultT
-  restoreM = defaultRestoreM runStMResultT
+  type StM (ResultT a m) b
+    = ComposeSt (ResultT a) m b
+  liftBaseWith = defaultLiftBaseWith
+  restoreM = defaultRestoreM
  {-# INLINE liftBaseWith #-}
  {-# INLINE restoreM #-}

@@ -235,8 +236,7 @@ withError :: (MonadError e m) => (e' -> e) -> GenericResult e' 
a -> m a
withError f = genericResult (throwError . f) return

-- | Changes the error message of a @ResultT@ value, if present.
-withErrorT :: (Monad m, Error e)
-           => (e' -> e) -> ResultT e' m a -> ResultT e m a
+withErrorT :: (Monad m, Error e) => (e' -> e) -> ResultT e' m a -> ResultT e m 
a

This is just a formatting change, right? In that case let's keep the old version, unless there is a reason to change it.

(And if there is a reason to change it, it should be a separate patch, as the change is not related to the monad-control instances.)

withErrorT f = ResultT . liftM (withError f) . runResultT

-- | Lift a 'Result' value to any 'MonadError'. Since 'ResultT' is itself its
diff --git a/src/Ganeti/Logging/WriterLog.hs b/src/Ganeti/Logging/WriterLog.hs
index 5e3d3bb..33bf53d 100644
--- a/src/Ganeti/Logging/WriterLog.hs
+++ b/src/Ganeti/Logging/WriterLog.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeFamilies,
             MultiParamTypeClasses, GeneralizedNewtypeDeriving,
-             StandaloneDeriving #-}
+             StandaloneDeriving, UndecidableInstances #-}

{-| A pure implementation of MonadLog using MonadWriter

@@ -109,19 +109,18 @@ instance (Monad m) => MonadLog (WriterLogT m) where
  logAt = curry (WriterLogT . tell . singleton)

instance MonadTransControl WriterLogT where
-    newtype StT WriterLogT a =
-      StWriterLog { unStWriterLog :: (a, LogSeq) }
+    type StT WriterLogT a = (a, LogSeq)
    liftWith f = WriterLogT . WriterT $ liftM (\x -> (x, mempty))
-                              (f $ liftM StWriterLog . runWriterLogT)
-    restoreT = WriterLogT . WriterT . liftM unStWriterLog
+                              (f runWriterLogT)
+    restoreT = WriterLogT . WriterT
    {-# INLINE liftWith #-}
    {-# INLINE restoreT #-}

instance (MonadBaseControl IO m)
         => MonadBaseControl IO (WriterLogT m) where
-  newtype StM (WriterLogT m) a
-    = StMWriterLog { runStMWriterLog :: ComposeSt WriterLogT m a }
-  liftBaseWith = defaultLiftBaseWith StMWriterLog
-  restoreM = defaultRestoreM runStMWriterLog
+  type StM (WriterLogT m) a
+    = ComposeSt WriterLogT m a
+  liftBaseWith = defaultLiftBaseWith
+  restoreM = defaultRestoreM
  {-# INLINE liftBaseWith #-}
  {-# INLINE restoreM #-}
diff --git a/src/Ganeti/THH/HsRPC.hs b/src/Ganeti/THH/HsRPC.hs
index 791b81d..e958591 100644
--- a/src/Ganeti/THH/HsRPC.hs
+++ b/src/Ganeti/THH/HsRPC.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE TemplateHaskell, FunctionalDependencies, FlexibleContexts,
-             GeneralizedNewtypeDeriving, TypeFamilies #-}
+             GeneralizedNewtypeDeriving, TypeFamilies, UndecidableInstances #-}
-- {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}

{-| Creates a client out of list of RPC server components.
@@ -70,11 +70,10 @@ newtype RpcClientMonad a =
            MonadError GanetiException)

instance MonadBaseControl IO RpcClientMonad where
-  newtype StM RpcClientMonad b = StMRpcClientMonad
-    { runStMRpcClientMonad :: StM (ReaderT Client ResultG) b }
+  type StM RpcClientMonad b = StM (ReaderT Client ResultG) b
  liftBaseWith f = RpcClientMonad . liftBaseWith
-                   $ \r -> f (liftM StMRpcClientMonad . r . runRpcClientMonad)
-  restoreM = RpcClientMonad . restoreM . runStMRpcClientMonad
+                   $ \r -> f (r . runRpcClientMonad)
+  restoreM = RpcClientMonad . restoreM

-- * The TH functions to construct RPC client functions from RPC server ones

diff --git a/src/Ganeti/WConfd/Monad.hs b/src/Ganeti/WConfd/Monad.hs
index 683f268..e4904f7 100644
--- a/src/Ganeti/WConfd/Monad.hs
+++ b/src/Ganeti/WConfd/Monad.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies,
-             GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE TemplateHaskell #-}
+             GeneralizedNewtypeDeriving,
+             TemplateHaskell, UndecidableInstances #-}

{-| All RPC calls are run within this monad.

@@ -178,11 +178,10 @@ newtype WConfdMonadInt a = WConfdMonadInt
  deriving (Functor, Applicative, Monad, MonadIO, MonadBase IO, MonadLog)

instance MonadBaseControl IO WConfdMonadInt where
-  newtype StM WConfdMonadInt b = StMWConfdMonadInt
-    { runStMWConfdMonadInt :: StM WConfdMonadIntType b }
+  type StM WConfdMonadInt b = StM WConfdMonadIntType b
  liftBaseWith f = WConfdMonadInt . liftBaseWith
-                   $ \r -> f (liftM StMWConfdMonadInt . r . getWConfdMonadInt)
-  restoreM = WConfdMonadInt . restoreM . runStMWConfdMonadInt
+                   $ \r -> f (r . getWConfdMonadInt)
+  restoreM = WConfdMonadInt . restoreM

-- | Runs the internal part of the WConfdMonad monad on a given daemon
-- handle.
-- 1.7.10.4


The rest is OK, thanks!

Reply via email to