{-# OPTIONS -XImpredicativeTypes -fno-warn-deprecated-flags -XEmptyDataDecls -XGADTs -XLiberalTypeSynonyms -XFlexibleInstances -XScopedTypeVariables #-} -- See #1627. The point is that we should get nice -- compact code for Foo -- In GHC 7.0 this fails, and rightly so. module M(foo) where import Control.Monad import Control.Monad.ST import Data.Array.ST data E' v m a where E :: m a -> E' RValue m a V :: m a -> (a -> m ()) -> E' v m a data LValue data RValue type E m a = E' RValue m a type V m a = E' LValue m a {-# INLINE runE #-} runE :: E' v m a -> m a runE (E t) = t runE (V t _) = t instance Monad m => Functor (E' RValue m) where {-# INLINE fmap #-} fmap f x = liftM f x instance Monad m => Applicative (E' RValue m) where {-# INLINE pure #-} pure x = return x {-# INLINE (<*>) #-} (<*>) = ap instance (Monad m) => Monad (E' RValue m) where {-# INLINE return #-} return x = E $ return x {-# INLINE (>>=) #-} x >>= f = E $ do x' <- runE x runE (f x') liftArray :: forall arr m a i . (Ix i, MArray arr a m) => arr i a -> E m (forall v . [E m i] -> E' v m a) {-# INLINE liftArray #-} liftArray a = E (do let ix :: [E m i] -> m i ix [i] = runE i {-# INLINE f #-} f is = V (ix is >>= readArray a) (\ x -> ix is >>= \ i -> writeArray a i x) return f ) {-# INLINE liftE2 #-} liftE2 :: (Monad m) => (a -> b -> c) -> E' va m a -> E' vb m b -> E m c liftE2 op x y = E $ do x' <- runE x y' <- runE y return (x' `op` y') {-# INLINE plus #-} plus :: (Monad m) => E m Int -> E m Int -> E m Int plus = liftE2 (+) foo :: forall s . STArray s Int Int -> ST s Int foo ma = runE $ do a <- liftArray ma let one :: E (ST t) Int one = return 1 a[one] `plus` a[one]