【问题标题】:Understanding this simple Reader monad example理解这个简单的 Reader monad 示例
【发布时间】:2021-08-06 08:32:17
【问题描述】:

我正在尝试理解 Reader monad,我正在关注这个答案 https://stackoverflow.com/a/14179721/10116440,其中包含以下示例:

 import Control.Monad.Reader

 data GameState = NotOver | FirstPlayerWin | SecondPlayerWin | Tie

 data Game position
   = Game {
           getNext :: position -> [position],
           getState :: position -> GameState
          }

 getNext' :: position -> Reader (Game position) [position]
 getNext' position
   = do game <- ask
        return $ getNext game position

 getState' :: position -> Reader (Game position) GameState
 getState' position
   = do game <- ask
        return $ getState game position


 negamax :: Double -> position -> Reader (Game position) Double
 negamax color position
     = do state <- getState' position 
          case state of
             FirstPlayerWin -> return color
             SecondPlayerWin -> return $ negate color
             Tie -> return 0
             NotOver -> do possible <- getNext' position
                           values <- mapM ((liftM negate) . negamax (negate color)) possible
                           return $ maximum values

首先我不明白的是return $ getNext game positiongetNext,当应用于 game 时,返回 position -&gt; [position]。这在应用于position 时返回[position]。所以return $ getNext game position 行应该返回Reader (Game position) [position] 以外的其他东西,我不知道这是什么东西,因为我不知道return 是如何为Reader monad 定义的。

无论如何,Game 中的哪个“实例”将 ask 返回?我不明白,这段代码中没有。另外,runReader 永远不会被调用,那么getNextgetStatenegamaxReader 结果是用来做什么的?

谁能完成这个示例,说明runReader 将如何在这段代码中实际运行,以及ask 返回哪个game 实例?

另外,为什么是Reader env a 而不仅仅是Reader a

【问题讨论】:

  • 你问,“为什么是Reader env a 而不仅仅是Reader a?”。让我转过头来:假设我们以Reader a 的想法运行;你对data Reader a = {- ... -}的RHS有什么建议?

标签: haskell monads


【解决方案1】:

您的帖子中有很多问题 - 这完全违反了 StackOverflow 规则。不过,我会一一回答:

为什么return $ getNext game position

确实,getNext game position 返回 [position] 类型的东西。现在看看return 函数——它的类型是Monad m =&gt; a -&gt; m a。在这种情况下,mReader (Game position)(不是 Reader (Game position) a,也不仅仅是 ReaderReader 本身不是 Monad。Reader something 是)。如果您将a 实例化为[position](如应用),您将得到Reader (Game position) [position] 声明。

Game 的哪个“实例”将 ask 返回?

ask 是来自Control.Monad.Reader 的实用程序。一般来说,Reader 是一个处理某些环境的 monad。 ask :: Reader env env 是一个只会导致该环境的操作。例如

runReader ask 123 == 123

所以,回答你的问题,它将返回隐藏在Reader 的外套下的当前处理的game

谁能完成这个例子

我不知道这里的“完整”是什么意思,但是runReader 的示例用法:

runReader (negamax 1.0 123) Game{getNext = \x -> [x], getState = \x -> NotOver}

为什么是Reader env a 而不仅仅是Reader a

因为Reader env 描述了具有env 类型的“背景”值的计算。如果没有env,这将毫无意义——Reader 的意义在于拥有该值并且需要知道其类型。如果你不喜欢每次都写,你可以写

type GameMonad position = Reader (Game position)

【讨论】:

    猜你喜欢
    • 2018-03-26
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多