gpt4 book ai didi

monads - Monad 变压器 – 显式提升

转载 作者:行者123 更新时间:2023-12-02 03:57:52 27 4
gpt4 key购买 nike

我正在阅读现实世界 Haskell 中的 monad 转换器。在以下示例中,堆栈为 Writer在顶部StateReader之上在IO之上。

{-# 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

我(认为我)明白如何简单地调用 ask , getput因为这些是在 MonadReader 中定义的, MonadWriterMonadState类型类,并且有诸如 MonadWriter (StateT s m) 之类的实例等等。

不明白是为什么我不能明确lift从下层到当前 monad 转换器的 Action 。在 constrainedCount如果我理解正确的话,我在 Reader monad 中,并且我认为两者都是 st <- getst <- lift get应该管用。 (tell 和 lift . lift .tell should be the same). If I change st <- get to st <- lift get` 我收到错误

Couldn't match type `t0 m0' with `MyApp'
Expected type: MyApp ()
Actual type: t0 m0 ()

它告诉我的很少......我对此的理解完全错误吗?

最佳答案

让我们看一下lift get的类型:

lift get :: (MonadTrans t, MonadState a m) => t m a

但是你的 MyApp 不是一个 monad 转换器,它只是一个 monad。但里面的东西当然是,所以如果你使用

    st <- MyA $ lift get

它有效。

关于monads - Monad 变压器 – 显式提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18519774/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com