1

我想让我的一些代码更“单子”,并使用 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

是否有意义?是否可以?如果是,我应该放什么来代替????我想真正的问题是,实现这种事情的好方法是什么?你会推荐什么设计?

4

2 回答 2

4

您可以Reader与using 混合ST使用ReaderT。像这样的东西:

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]
于 2012-06-30T11:57:19.060 回答
1

你能不使用ReaderT单子变压器并将其堆叠在上面ST吗?喜欢这里:http ://book.realworldhaskell.org/read/monad-transformers.html

于 2012-06-30T11:44:05.230 回答