Luc*_*cas 1 iteration recursion haskell if-statement list
我觉得我从根本上误解了 Haskell 的编写方式。我的代码旨在用作 Othello 游戏的原始 AI 的评估函数。本质上,我希望我的代码循环遍历一个棋子列表,每个棋子由一个由位置(Int,Int)和一个 Col(颜色,黑色或白色)组成的元组表示,并给出一个预期的移动,确定移动的好坏是。
我判断一个举动的价值的方式是基于几个因素:
由于 Haskell 没有循环结构,因此我似乎需要递归地实现它,因此我的代码如下:
eval :: Position -> [(Position, Col)] -> Col -> GameState -> Int -> Int
eval move pieces moveColour gameState score = do
let moveX = fst move
let moveY = snd move
let piece = head(pieces)
let pieceColour = snd piece
let pieceX = fst fst piece
let pieceY = snd fst piece
if (moveColour == pieceColour) then
if (moveX == pieceX) then
if (moveY > pieceY) then
let newScore = score + (countOtherColour 0 moveY pieceY (pieces gameState) moveColour 0)
--recurse
if (tail(pieces) == []) then
return newScore
else
return eval move tail(pieces) moveColour gameState newScore
else
let newScore = score + (countOtherColour 0 pieceY moveY (pieces gameState) moveColour 0)
--recurse
if (tail(pieces) == []) then
return newScore
else
return eval move tail(pieces) moveColour gameState newScore
else
if (moveY == pieceY) then
if (moveX > pieceX) then
let newScore = score + (countOtherColour 1 moveX pieceX (pieces gameState) moveColour 0)
--recurse
if (tail(pieces) == []) then
return newScore
else
return eval move tail(pieces) moveColour gameState newScore
else
let newScore = score + (countOtherColour 1 pieceX moveX (pieces gameState) moveColour 0)
--recurse
if (tail(pieces) == []) then
return newScore
else
return eval move tail(pieces) moveColour gameState newScore
else
--recurse
if (tail(pieces) == []) then
return score
else
return eval move tail(pieces) moveColour gameState score
else
--recurse
if (tail(pieces) == []) then
return score
else
return eval move tail(pieces) moveColour gameState score
countOtherColour :: Int -> Int -> Int -> [(Position, Col)] -> Col -> Int -> Int
countOtherColour xyFlag upper lower pieces turnColour score = do
--if xyFlag == 0 it's y aligned if 1 it's x aligned
let piece = head(pieces)
let pieceColour = other (snd piece)
let x = fst fst piece
let y = snd fst piece
if (pieceColour == turnColour) then
if (xyFlag == 0) then
if (upper > x && x > lower) then
let newScore = score+1
--recurse
if (tail(pieces) == []) then
return newScore
else
return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
else
--recurse
if (tail(pieces) == []) then
return score
else
return countOtherColour xyFlag upper lower tail(pieces) turnColour score
else
if (upper > y && y > lower) then
let newScore = score+1
--recurse
if (tail(pieces) == []) then
return newScore
else
return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
else
--recurse
if (tail(pieces) == []) then
return score
else
return countOtherColour xyFlag upper lower tail(pieces) turnColour score
else
--recurse
if (tail(pieces) == []) then
return score
else
return countOtherColour xyFlag upper lower tail(pieces) turnColour score
Run Code Online (Sandbox Code Playgroud)
但是,此代码无法编译。我在第一行收到“if”上的“解析错误”,内容如下:
if (tail(pieces) == []) then
Run Code Online (Sandbox Code Playgroud)
这让我相信,我构建这段代码的方式的一些基本原理是错误的。我想澄清一下,我不是在找人来解决我的实现,只是找人向我解释我的实现是如何有缺陷的,以及如何以正确的方式实现递归来构建我的代码的一般指南.
如果您已经阅读了这么多,谢谢,我期待着阅读您的回复。
当let
在 a 之外时do
,它需要一个in
,例如:
-- correct
x =
let a = 5
in a + 37
-- incorrect
x =
let a = 5
a + 37
Run Code Online (Sandbox Code Playgroud)
所以当你if
在 a 之后出现时let
,in
它前面应该有一个right :
let newScore = score+1
-- recurse
in if (tail(pieces) == []) then
...
Run Code Online (Sandbox Code Playgroud)
除此之外,您的代码中还有很多其他可以更简洁的内容。我不会介绍所有这些,只会举几个例子。
一个例子是let
连续的多个绑定不需要let
每个绑定:
x =
let a = 5
b = 37
in a + b
Run Code Online (Sandbox Code Playgroud)
同样,条件if
不需要括号,函数调用也不需要:
if tail pieces == [] then
Run Code Online (Sandbox Code Playgroud)
当我们在做的时候:通过null
函数测试空列表而不是比较== []
:
if null (tail pieces) then
Run Code Online (Sandbox Code Playgroud)