Using newtype for Block will support s existential. Otherwise, it leaks out
With original definition:
type Block = forall s . STVector s Int -> ST s Int type Exp = Int -> Int -> Block
You can simplify the failure example ( main ):
g . block
You would like it to be as follows:
g . block :: [Block] -> Int
But since the written types of components are:
block :: forall s. [forall s0. STVector s0 Int -> ST s0 Int] -> (STVector s Int -> ST s Int) g :: (forall s1. STVector s1 Int -> ST s1 Int) -> Int
Then, when compiled with (.) , The GHC saves s general:
g . block :: forall s . [forall s0. STVector s0 Int -> ST s0 Int] -> Int
and trying to combine:
forall s1. STVector s1 Int -> ST s1 Int -- and (STVector s Int -> ST s Int)
With newtype everything works fine (and ImpredicativeTypes not needed):
{-# LANGUAGE RankNTypes #-} import Control.Monad.ST import Data.Vector.Unboxed (Vector) import qualified Data.Vector.Unboxed as U import Data.Vector.Unboxed.Mutable (STVector) import qualified Data.Vector.Unboxed.Mutable as UM type Exp = Int -> Int -> Block newtype Block = Block { unBlock :: forall s . STVector s Int -> ST s Int } block :: [Block] -> Block block [] = Block $ \_ -> return 0 -- mapM doesn't work, either - ok, I kinda see why block (e:es) = Block $ \a -> do x <- unBlock ea xs <- unBlock (block es) a return $ x + xs copy :: Exp copy ij = Block $ \a -> do aj <- a `UM.unsafeRead` j UM.unsafeWrite ai aj return 1 f :: Block -> Vector Int -> Int f (Block blk) ua = runST $ U.thaw ua >>= blk g :: Block -> Int g blk = f blk $ U.fromListN 12 [1..] main = print . g $ block [copy 10 1]
source share