首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Monad变压器.显式提升

Monad变压器.显式提升
EN

Stack Overflow用户
提问于 2013-08-29 19:48:50
回答 1查看 413关注 0票数 3

我在读关于真实世界中的单台变压器的文章。在下面的示例中,堆栈是WriterState顶部,在Reader之上,在IO之上。

代码语言:javascript
运行
复制
{-# Language GeneralizedNewtypeDeriving #-}

import Control.Monad
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Writer
import System.Directory
import System.FilePath

data AppConfig = AppConfig {
      cfgMaxDepth :: Int
    } deriving Show

data AppState = AppState {
      stDeepestReached :: Int
    } deriving Show

newtype MyApp a = MyA {
      runA :: WriterT [(FilePath,Int)] (StateT AppState (ReaderT AppConfig IO)) a
    } deriving (Monad, MonadIO, Functor, MonadReader AppConfig,
                MonadWriter [(FilePath,Int)], MonadState AppState)

runApp :: MyApp a -> Int -> IO ([(FilePath,Int)], AppState)
runApp k maxDepth = let config = AppConfig maxDepth
                        state' = AppState 0
                     in runReaderT (runStateT (execWriterT $ runA k) state') config

constrainedCount :: Int -> FilePath -> MyApp ()
constrainedCount curDepth path = do
  contents <- liftIO . getDirectoryContents $ path
  cfg <- ask
  let maxDepth = cfgMaxDepth cfg
  tell [(path,curDepth)]
  forM_ (filter (\d' -> d' /= ".." && d' /= ".") contents) $ \d -> do
    let newPath = path </> d
    isDir <- liftIO $ doesDirectoryExist newPath
    when (isDir && curDepth < maxDepth) $ do
         let newDepth = curDepth+1
         st <- get
         when (stDeepestReached st < newDepth) $
             put st { stDeepestReached = newDepth }
         constrainedCount newDepth newPath

main = runApp (constrainedCount 0 "/tmp") 2 >>= print

我(认为我)理解如何简单地调用askgetput,因为它们是在MonadReaderMonadWriterMonadState类型类中定义的,还有一些实例,如MonadWriter (StateT s m)等等。

我不明白的是,为什么我不能显式lift一个动作从下面的层到当前的单台转换器。在constrainedCount中,如果我理解正确的话,我就在Reader中,我认为st <- getst <- lift get都应该工作。( tell和电梯。抬起来。告诉should be the same). If I changest <-获取tost <- lift‘i得到错误

代码语言:javascript
运行
复制
Couldn't match type `t0 m0' with `MyApp'
Expected type: MyApp ()
Actual type: t0 m0 ()

这几乎没有告诉我..。我对这件事的理解完全错误吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-29 20:11:54

让我们看看lift get的类型

代码语言:javascript
运行
复制
lift get :: (MonadTrans t, MonadState a m) => t m a

但是你的MyApp不是一个单一的变压器,它只是一个单一的。但内在的是,当然,如果你用

代码语言:javascript
运行
复制
    st <- MyA $ lift get

它起作用了。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18519774

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档