summaryrefslogtreecommitdiff
path: root/testsuite/tests/ghc-regress/simplCore/should_compile/simpl017.hs
blob: 8c801a44f3e9bbd3fbb9afc54f2638e8e1f9eca2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{-# OPTIONS -XImpredicativeTypes -fno-warn-deprecated-flags -XEmptyDataDecls -XGADTs -XLiberalTypeSynonyms -XFlexibleInstances -XScopedTypeVariables #-}

-- See Trac #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.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) => 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]