gpt4 book ai didi

haskell - 如何在 ReaderT 中使用列表 monad?

转载 作者:行者123 更新时间:2023-12-02 17:49:29 24 4
gpt4 key购买 nike

如何使用 Reader/ReaderT询问列表类型,例如[(Int, Int)] 然后在列表 monad 内执行计算(要求的类型)?

下面是我损坏的代码,为了清晰起见,缩短了代码:

attempt :: Int -> Int -> ReaderT [(Int,Int)] [] [[Int]]
attempt start end =
do (s0, e0) <- ask
return [0]

为了让您了解我正在尝试做什么,这里是相同的函数,使用列表 monad 但不使用 Reader:

paths :: [(Int, Int)] -> Int -> Int -> [[Int]]
paths edges start end =
if start == end
then return [end]
else do (s0, e0) <- edges
guard $ s0 == start
subpath <- paths edges e0 end
return $ s0 : subpath

我使用 ReaderT 是因为我正在学习 monad 转换器。这是使用 Reader 和 Writer 以及列表 monad 来实现路径的更大问题的一部分。

最佳答案

这里的技巧是使用 lift 将列表 monad(即 [a])转换为 ReaderT env [] 通过使用 lift:

lift :: (Monad m, MonadTrans t) => m a -> t m a

或专门针对您的 monad 堆栈:

lift :: [a] -> ReaderT [(Int,Int)] [] a

ask 返回包装在 ReaderT monad 中的状态(即 [(Int, Int)]),例如:

ask :: ReaderT [(Int, Int)] [] [(Int, Int)]

我们希望将其转换为同一 monad 中的另一个值,但类型为:

??? :: ReaderT [(Int, Int)] [] (Int, Int)

因此替代方案由 monad 跟踪,而不是在输出中跟踪。考虑基本函数 >>=:

(>>=) :: Monad m => m a -> (a -> m b) -> m b

您应该能够看到我们拥有所需的所有部件。使用ask >>= lift:

  1. 第一个参数是 ReaderT [(Int, Int)] [] [(Int, Int)],表示 a[(Int, Int) )],而 mReaderT [(Int, Int)] []
  2. 我们希望结果 m bReaderT [(Int, Int)] [] (Int, Int),因此 b(整数,整数)
  3. 因此该函数需要类型[(Int, Int)] -> ReaderT [(Int, Int)] [] (Int, Int)。如果将 lift 函数中的 a 替换为 (Int, Int),则它是完美匹配,意味着表达式 ask >>= lift 做你想要的。

您遇到的另一个错误是 ReaderT monad 的输出类型 - 因为它包含一个列表 monad,您不需要将结果包装在另一对括号中。 ReaderT 状态 [] 已经包含多个结果的概念,在本例中,单个结果是显示图形路径的 [Int]

这是工作代码:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Main where
import Control.Monad.Reader
import Control.Applicative


paths :: Int -> Int -> ReaderT [(Int,Int)] [] [Int]
paths start end = do
if start == end
then return [end]
else do
(s0, e0) <- ask >>= lift
guard $ s0 == start
(s0 :) <$> paths e0 end


input :: [(Int, Int)]
input = [(1,2), (2,7), (3,4), (7, 3), (7, 5), (5, 3)]

test :: [[Int]]
test = runReaderT (paths 2 4) input


> test
[[2,7,3,4],[2,7,5,3,4]]

我希望能解释清楚。在这种情况下,我可能会坚持使用原始解决方案(单独使用 Reader 通常不是很有用),但了解如何理解和操作 monad 和 monad 转换器的类型是有好处的.

关于haskell - 如何在 ReaderT 中使用列表 monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24178800/

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