gpt4 book ai didi

Haskell Monad 函数

转载 作者:行者123 更新时间:2023-12-02 23:19:45 25 4
gpt4 key购买 nike

我正在学习 Haskell 教程,并得到了这段与移动国际象棋中的马有关的代码:

import Control.Monad

type KnightPos = (Int,Int)

moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = do
(c',r') <- [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)
,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)
]
guard (c' `elem` [1..8] && r' `elem` [1..8])
return (c',r')

in3 :: KnightPos -> [KnightPos]
in3 start = return start >>= moveKnight >>= moveKnight >>= moveKnight

canReachIn3 :: KnightPos -> KnightPos -> Bool
canReachIn3 start end = end `elem` in3 start

练习是修改函数,以便 canReachIn3 告诉您可以采取哪些 Action 来到达最终位置(如果有可能)。

本教程基本上没有练习,所以我在处理像这样的基本内容时遇到了麻烦...我正在考虑将所有 3 个函数的返回值更改为 [[KnightPos]],其中 1 个大列表包含每个函数的列表可能的 Action 顺序。这可能会涉及 moveKnight 有一个 [KnightPos] 参数而不是 KnightPos 参数,这会破坏 monad 的全部意义,对吗?

任何帮助/想法将不胜感激,谢谢。

最佳答案

如果您发现简单的旧列表操作对您来说更自然,那么在思考这段代码时,稍微从 Monad 概念中退一步可能会有所帮助。因此,您可以将示例代码重写为:

type KnightPos = (Int,Int)

moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = filter legal candidates where
candidates = [(c+2,r-1), (c+2,r+1), (c-2,r-1), (c-2,r+1),
(c+1,r-2), (c+1,r+2), (c-1,r-2), (c-1,r+2)]
legal (c',r') = c' `elem` [1..8] && r' `elem` [1..8]

in3 :: KnightPos -> [KnightPos]
in3 start = concatMap moveKnight (concatMap moveKnight (moveKnight start))

canReachIn3 :: KnightPos -> KnightPos -> Bool
canReachIn3 start end = end `elem` in3 start

secret 武器在 concatMap 。您可能已经知道,它与>>=同义。在 List monad,但现在将其视为映射 KnightPos -> [KnightPos] 类型的函数可能会更有帮助。在列表上[KnightPos]生成列表的列表 [[KnightPos]] ,然后将结果展平回单个列表。

好吧,现在我们已经暂时放弃了 monad,让我们回顾一下这个难题......假设您的初始 KnightPos(4,4) ,并且您想要跟踪从该位置开始的所有可能的移动序列。因此定义另一个类型同义词:

type Sequence = [KnightPos]

那么你会想要moveKnight对这些序列进行操作,从序列中的最后一个位置找到所有可能的移动:

moveKnight :: Sequence -> [Sequence]

所以从序列 [(4,4)] 开始,我们会得到序列列表:[[(4,4), (6,3)], [(4,4), (6,5)], [(4,4), (2,3)], ... ] 。那么我认为您需要对 in3 进行唯一的更改是相应地修复其类型签名:

in3 :: Sequence -> [Sequence]

我认为实际的实现不会改变。最后,你会想要canReachIn3看起来像:

canReachIn3 :: KnightPos -> KnightPos -> [Sequence]

我故意将实现细节留在这里,因为我不想完全破坏你的谜题,但我希望我已经在这里说明了这一点,即没有任何特别“特别”的东西关于一个列表,或者一个列表的列表,或者其他什么。我们真正所做的只是替换 KnightPos -> [KnightPos] 类型的函数。具有类型 Sequence -> [Sequence] 的新函数——形状几乎一样。因此,使用任何感觉自然的风格填写每个函数的实现,然后一旦你让它工作,返回到单子(monad)风格,替换 concatMap>>=等等。

关于Haskell Monad 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8396311/

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