Reader中的runST

时间:2012-06-30 11:14:56

标签: haskell

我想让我的一些代码更“monadic”并使用Reader monad而不是传递一个共同的环境。但在某些地方我必须使用可变矢量,因此ST monad也是如此;为了让事情变得有趣,ST动作需要访问环境(但其余的功能却没有)。换句话说,这有效:

aux :: Int -> Reader Env Double
aux i = -- something

bla :: [a] -> Reader Env Double
bla l = do e <- ask
           return $ runST $ do -- something producing an Int
                               let o = runReader (aux i) e
                               -- something else depending on o
                               return something

但感觉非常丑陋和错误,是一种令人费解的方式仍然明确地传递环境;我希望bla看起来更像这样:

bla :: [a] -> Reader Env Double
bla l = return $ runST $ do -- something producing an Int
                            o <- ??? aux i
                            -- something depending on o
                            return something

有意义吗?可能吗?如果是,我必须代替???放置什么?我想真正的问题是,实现这种事情的好方法是什么?你会推荐什么设计?

2 个答案:

答案 0 :(得分:4)

您可以使用ReaderSTReaderT混合使用。这样的事情:

import Data.Array.ST
import Control.Monad.ST
import Control.Monad.Reader

type Env = String

type ReaderST s = ReaderT Env (ST s)

foo :: ReaderST s [Int]
foo = do
  str <- ask
  let len = length str
  a <- lift (newArray (0, len - 1) 0 :: ST s (STUArray s Int Int))
  a' <- lift $ mapArray (+ 2) a
  es <- lift $ getElems a'
  return es

run :: [Int]
run = runST $ runReaderT foo "xyz"

-- > run
-- [2,2,2]

答案 1 :(得分:1)

你能否使用ReaderT monad变换器并将其堆叠在ST之上?就像这里:http://book.realworldhaskell.org/read/monad-transformers.html