runMalaBlocks :: Covariance a => a -> (Vector Double -> (Double,Vector Double)) 
         ->  Int -> Double -> Int -> Vector Double -> [Vector Int] 
         -> RIO [Vector Double]
runMalaBlocks cov  postgrad nsam truncN thinN init  vixs = go nsam initBlocks init []  where
  initBlocks = flip map vixs $ \vix-> 
     (restrict vix cov, 
      MalaPar (VS.backpermute init vix) 0 (fromList [0]) 0.001 0 0 False thinN truncN,
      vix)
  go 0 _ _ vs = return vs
  go n blocks0 v0 vs = do
        (!v1, blocks1) <- sample $ blockMala1 postgrad v0 blocks0
        let (_,mpLast,_) = last blocks1 
        io $ print $ (n, mpPi mpLast, map (\(_,mp,_) -> mpSigma mp) blocks1)
        let newChainRes = if thinN == 0 || n `mod` thinN ==0
                             then v1 : vs
                             else vs
        go (n-1) blocks1 v1 newChainRes 


{-runMala :: Matrix Double -> (Vector Double -> (Double,Vector Double)) 
         ->  Int -> Vector Double -> RIO [(Double,Vector Double)]
runMala cov postgrad nsam init = go nsam mp1 [] where
  go 0 mpar xs = do io $ putStrLn $ "MALA accept = "++show (mpAccept mpar/mpCount mpar)
                    io $ putStrLn $ "MALA sigma = "++show (mpSigma mpar)
                    return xs
  go n y xs = do y1 <- sample $ mala1 cov postgrad y
                 go (n-1) y1 $ (mpPi y1, mpXi y1):xs 
  (pi, gradi) = postgrad init
  mp1 =  MalaPar init pi (gradi)  1 0 0 False -}
runMalaBlocks :: Covariance a => a -> (Vector Double -> (Double,Vector Double)) 
         ->  Int -> Double -> Int -> Vector Double -> [Vector Int] 
         -> RIO [Vector Double]
runMalaBlocks cov  postgrad nsam truncN thinN init  vixs = go nsam initBlocks init []  where
  initBlocks = flip map vixs $ \vix-> 
     (restrict vix cov, 
      MalaPar (VS.backpermute init vix) 0 (fromList [0]) 0.001 0 0 False thinN truncN,
      vix)
  go 0 _ _ vs = return vs
  go n blocks0 v0 vs = do
        (!v1, blocks1) <- sample $ blockMala1 postgrad v0 blocks0
        let (_,mpLast,_) = last blocks1 
        io $ print $ (n, mpPi mpLast, map (\(_,mp,_) -> mpSigma mp) blocks1)
        let newChainRes = if thinN == 0 || n `mod` thinN ==0
                             then v1 : vs
                             else vs
        go (n-1) blocks1 v1 newChainRes 


{-runMala :: Matrix Double -> (Vector Double -> (Double,Vector Double)) 
         ->  Int -> Vector Double -> RIO [(Double,Vector Double)]
runMala cov postgrad nsam init = go nsam mp1 [] where
  go 0 mpar xs = do io $ putStrLn $ "MALA accept = "++show (mpAccept mpar/mpCount mpar)
                    io $ putStrLn $ "MALA sigma = "++show (mpSigma mpar)
                    return xs
  go n y xs = do y1 <- sample $ mala1 cov postgrad y
                 go (n-1) y1 $ (mpPi y1, mpXi y1):xs 
  (pi, gradi) = postgrad init
  mp1 =  MalaPar init pi (gradi)  1 0 0 False -}
runMalaBlocks cov  postgrad nsam truncN thinN init  vixs = go nsam initBlocks init []  where
  initBlocks = flip map vixs $ \vix-> 
     (restrict vix cov, 
      MalaPar (VS.backpermute init vix) 0 (fromList [0]) 0.001 0 0 False thinN truncN,
      vix)
  go 0 _ _ vs = return vs
  go n blocks0 v0 vs = do
        (!v1, blocks1) <- sample $ blockMala1 postgrad v0 blocks0
        let (_,mpLast,_) = last blocks1 
        io $ print $ (n, mpPi mpLast, map (\(_,mp,_) -> mpSigma mp) blocks1)
        let newChainRes = if thinN == 0 || n `mod` thinN ==0
                             then v1 : vs
                             else vs
        go (n-1) blocks1 v1 newChainRes 


{-runMala :: Matrix Double -> (Vector Double -> (Double,Vector Double)) 
         ->  Int -> Vector Double -> RIO [(Double,Vector Double)]
runMala cov postgrad nsam init = go nsam mp1 [] where
  go 0 mpar xs = do io $ putStrLn $ "MALA accept = "++show (mpAccept mpar/mpCount mpar)
                    io $ putStrLn $ "MALA sigma = "++show (mpSigma mpar)
                    return xs
  go n y xs = do y1 <- sample $ mala1 cov postgrad y
                 go (n-1) y1 $ (mpPi y1, mpXi y1):xs 
  (pi, gradi) = postgrad init
  mp1 =  MalaPar init pi (gradi)  1 0 0 False -}