I have a body of code that uses a monad to abstract whether the actual implementation runs inside ST or IO. Removing the extra layer of abstraction and just substituting concrete types gives a huge speedup (~4.5x) due to the inlining and missing typeclass function call overhead. I was thinking of getting some of that performance by using a specialize pragma, but I'm getting a rather meaningless warning from the compiler. I can't make a simple reproduction case as the simple example seems to work, and I don't know what's causing the difference in my actual program.
Basically, my program does this:
{-# LANGUAGE FlexibleInstances, RankNTypes #-}
module STImpl (runAbstractST, MonadAbstractIOST(..), ReaderST) where
import Control.Monad.Reader
import Control.Monad.ST
class Monad m => MonadAbstractIOST m where
addstuff :: Int -> m Int
type ReaderST s = ReaderT (Int) (ST s)
instance MonadAbstractIOST (ReaderST s) where
addstuff a = return . (a +) =<< ask
runAbstractST :: (forall s. ReaderST s a) -> a
runAbstractST f = runST $ runReaderT f 99
and
module Main (main) where
import STImpl
import Control.Monad
{-# SPECIALIZE INLINE useAbstractMonad :: ReaderST s Int #-}
useAbstractMonad :: MonadAbstractIOST m => m Int
useAbstractMonad = foldM (\a b -> a `seq` return . (a +) =<< (addstuff b)) 0 [1..50000000]
main :: IO ()
main = do
let st = runAbstractST useAbstractMonad
putStrLn . show $ st
Now, here everything seems to work fine. But in my program I get
RULE left-hand side too complicated to desugar
let {
$dFunctor :: Functor (RSTSim s)
[LclId]
$dFunctor =
Control.Monad.Trans.Reader.$fFunctorReaderT
@ (MonadSim.SimState s)
@ (GHC.ST.ST s)
(GHC.ST.$fFunctorST @ s) } in
simulate
@ (Control.Monad.Trans.Reader.ReaderT
(MonadSim.SimState s) (GHC.ST.ST s))
(MonadSim.$fMonadSimReaderT
@ s
$dFunctor
(Control.Monad.Trans.Reader.$fMonadReaderT
@ (MonadSim.SimState s)
@ (GHC.ST.ST s)
(GHC.ST.$fMonadST @ s))
(Control.Monad.Trans.Reader.$fApplicativeReaderT
@ (MonadSim.SimState s)
@ (GHC.ST.ST s)
$dFunctor
(Control.Applicative.$fApplicativeST0
@ s (GHC.ST.$fFunctorST @ s))))
I don't understand what 'left-hand side', 'too complicated' and 'desugar' mean ;-)
It seems I have the same problem as described here: http://marc.info/?l=haskell-cafe&m=133242702914511
How do I diagnose this? How do I figure out what's causing the optimization to be disabled in my program?
Thanks!
For what it's worth, on the 7.10 RC1 this error no longer occurs, so it looks like the fix to https://ghc.haskell.org/trac/ghc/ticket/8848 may have helped.