1

コードの一部をより「モナド」にして、共通の環境を渡すのではなく Reader モナドを使用したいと考えています。しかし、どこかで変更可能なベクトルを使用する必要があるため、ST モナドも使用します。興味深いことに、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

ReaderST使って混ぜることができます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 に答える