首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应用置换生成骑士动作

应用置换生成骑士动作
EN

Code Review用户
提问于 2015-07-02 20:47:06
回答 1查看 413关注 0票数 5

我想更好地理解Haskell,尝试尽可能地扩展函子、应用程序和Monad的可能性,并研究它们的行为。因此,在给你一个哈斯克尔中,有一个练习从棋盘上给定的位置为骑士生成所有可能的动作:

moveKnight ::KnightPos -> KnightPos moveKnight (c,r) = filter onBoard (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),其中onBoard (c,r) =c elem 1.8 &r elem 1.8

现在我想,等等,我实际上可以生成列表[(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)],而不是硬编码它。所以我就是这么做的:

代码语言:javascript
复制
invert x
  | x == 1 = 2
  | x == 2 = 1
  | otherwise = 0

moves = [(c `f` a, r `g` (invert a)) |
         c <- [6],
         r <- [2],
         f <- [(+), (-)],
         g <- [(+), (-)],
         a <- [1, 2]]

-- generates: [(7,4),(8,3),(7,0),(8,1),(5,4),(4,3),(5,0),(4,1)]

因此,上面的代码工作正常,但代码看起来很难看。因为每个列表理解都等同于一次提升,所以上面的代码可以用liftA5重写:

代码语言:javascript
复制
liftA5 :: Applicative g => (a -> b -> c -> d -> e -> f) -> g a -> g b -> g c -> g d -> g e -> g f
liftA5 f a b c d e = f <A12gt; a <*> b <*> c <*> d <*> e

liftA5 (\c r f g a -> (c `f` a, r `g` (invert a))) [6] [2] [(+), (-)] [(+), (-)] [1,2]

我的问题是:

  • 是否有任何方法以更优雅的方式生成上述列表?
  • 如何将其推广到任意可能的排列?(这样我的代码就可以参数化,而不是固定在数字1和2,或者只是+和-等等)
  • 我能从这个练习中得到什么直觉、洞察力和教训?

我知道这是一种精心设计的情况,但它们有助于我更好地理解语言。

EN

回答 1

Code Review用户

发布于 2015-07-03 11:13:37

使用模式匹配,您可以编写:

代码语言:javascript
复制
invert 1 = 2
invert 2 = 1
invert n = 0 -- Error would be better in my opinion

您可以插入第6行和第2行,而不是从单个项目列表中提取它们。

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

https://codereview.stackexchange.com/questions/95616

复制
相关文章

相似问题

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