您好,我正在撰寫此代碼作為初學者 Haskell 專案,它解決了一個非常基本的掃雷器版本。細節并不重要,但我在 isGoal 函式的第 50 行不斷收到語法錯誤 運算式中的語法錯誤(意外的 `;',可能是由于布局錯誤)。此函式應該測驗 al 串列是否為空串列,如果是則回傳 true,但我不斷收到此語法錯誤。我是初學者,所以任何幫助表示贊賞
type Cell = (Int,Int)
data MyState = Null | S Cell [Cell] String MyState deriving Show
up :: MyState -> MyState
up (S (0, _) [_] _ _)= Null
up (S (0, _) (_:_) _ _)= Null
up (S (x,y) [c] "" s)= S ((x-1),y) [c] "up" (S (x,y) [c] "" s)
up (S (x,y) [c] b s)= S ((x-1),y) [c] "up" (S (x,y) [c] b s)
up (S (x,y) (c:cs) "" s)= S ((x-1),y) (c:cs) "up" (S (x,y) (c:cs) "" s)
up (S (x,y) (c:cs) b s)= S ((x-1),y) (c:cs) "up" (S (x,y) (c:cs) b s)
down :: MyState -> MyState
down (S (3, _) [_] _ _)= Null
down (S (3, _) (_:_) _ _)= Null
down (S (x,y) [c] "" s)= S ((x 1),y) [c] "down" (S (x,y) [c] "" s)
down (S (x,y) [c] b s)= S ((x 1),y) [c] "down" (S (x,y) [c] b s)
down (S (x,y) (c:cs) "" s)= S ((x 1),y) (c:cs) "down" (S (x,y) (c:cs) "" s)
down (S (x,y) (c:cs) b s)= S ((x 1),y) (c:cs) "down" (S (x,y) (c:cs) b s)
left :: MyState -> MyState
left (S (_, 0) [_] _ _)= Null
left (S (_, 0) (_:_) _ _)= Null
left (S (x,y) [c] "" s)= S (x,(y-1)) [c] "left" (S (x,y) [c] "" s)
left (S (x,y) [c] b s)= S (x,(y-1)) [c] "left" (S (x,y) [c] b s)
left (S (x,y) (c:cs) "" s)= S (x,(y-1)) (c:cs) "left" (S (x,y) (c:cs) "" s)
left (S (x,y) (c:cs) b s)= S (x,(y-1)) (c:cs) "left" (S (x,y) (c:cs) b s)
right :: MyState -> MyState
right (S (_, 3) [_] _ _)= Null
right (S (_, 3) (_:_) _ _)= Null
right (S (x,y) [c] "" s)= S (x,(y 1)) [c] "right" (S (x,y) [c] "" s)
right (S (x,y) [c] b s)= S (x,(y 1)) [c] "right" (S (x,y) [c] b s)
right (S (x,y) (c:cs) "" s)= S (x,(y 1)) (c:cs) "right" (S (x,y) (c:cs) "" s)
right (S (x,y) (c:cs) b s)= S (x,(y 1)) (c:cs) "right" (S (x,y) (c:cs) b s)
collect:: MyState -> MyState
collect (S l [a,b] d z) | l==a = (S l [b] "collect" (S l [a,b] d z))
| l==b = (S l [a] "collect" (S l [a,b] d z))
|otherwise =Null
check:: (MyState -> MyState) -> (MyState -> [MyState])
check f (S l [a,b] d z) = if f (S l [a,b] d z) == Null then [] else f (S l [a,b] d z)
nextMyStates:: MyState -> [MyState]
nextMyStates (S l [a,b] d z) = check(up (S l [a,b] d z) check(down (S l [a,b] d z) check(right (S l [a,b] d z) check(left (S l [a,b] d z) check(collect (S l [a,b] d z)
isGoal :: (MyState) -> (Bool)
isGoal (S l al d z) = if al == ([]) then True else False
search::[MyState]->MyState
search (S l al d z:xs) | isGoal S l al d z =(S l al d z)
| isGoal S l al d z ==False = search xs nextMyStates (S l al d z)
constructSolution :: MyState ->[String]
constructSolution (S l c d z) | z == Null = []
| d == Null = [] constructSolution (z p cs s k)
| otherwise = [d] constructSolution (z p cs s k)
solve :: Cell->[Cell]->[String]
solve (x,y) [(a,b),(c,d)] = constructSolution (search (nextMyStates S (x,y) [(a,b),(c,d)] "" Null))
uj5u.com熱心網友回復:
這比追蹤錯誤所需的代碼多得多。將來,請包含完整的錯誤訊息(那些總是有用的),但將代碼縮小到更小的內容。例如,您可以嘗試洗掉一個函式并查看錯誤是否仍然存在。
盡管如此,在這種情況下,從我們得到的小錯誤訊息中不難發現問題:nextMyStates
,之前的函式isGoal
,有不平衡的括號。
uj5u.com熱心網友回復:
您的功能不平衡nextMyStates
。例如
check(up (S l [a,b] d z)
,您可能指的是check $ up S l [a,b] d z
.
您可能還想閱讀 as-patterns,讓您可以大大簡化代碼:)
uj5u.com熱心網友回復:
nextMyStates
定義是罪魁禍首。
nextMyStates (S l [a,b] d z) = check(up (S l [a,b] d z) check(down (S l [a,b] d z) check(right (S l [a,b] d z) check(left (S l [a,b] d z) check(collect (S l [a,b] d z)
首先,讓我們通過拆分運算式而不是使用一條長得離譜的行來使其更具可讀性:
nextMyStates (S l [a,b] d z)
= check(up (S l [a,b] d z)
check(down (S l [a,b] d z)
check(right (S l [a,b] d z)
check(left (S l [a,b] d z)
check(collect (S l [a,b] d z)
此時很明顯,您已經完成了完全不必要的模式匹配,因為S l [a,b] d z
所有子運算式都使用了整體。由于這也是唯一的子句,因此不需要所有冗長的內容:只需將其全部匹配為一個變數
nextMyStates s
= check(up s
check(down s
check(right s
check(left s
check(collect s
最遲現在也很明顯決議錯誤是什么:有一堆不匹配的括號。
nextMyStates s
= check(up s)
check(down s)
check(right s)
check(left s)
check(collect s)
這仍然是不必要的冗長:你多次做同樣的事情,唯一的區別是s
在每種情況下應用的函式。發生這種情況時,通常最好將所有重復的部分排除在外;一種方法是制作函式串列,然后在串列理解中使用它們
[check $ f s | f <- [up, down, right, left, collect]]
最后,要連接所有結果,您可以使用該concat
函式:
nextMyStates s = concat [check $ f s | f <- [up, down, right, left, collect]]
順便說一句isGoal
,風格上也很糟糕。為什么人們一直在寫作if x then True else False
?這很愚蠢,就像在說“天氣下雨的屬性得到滿足”,而不是簡單的“天氣下雨”。括號也是不必要的。對于模式匹配中未使用的變數,約定是將它們全部設為_
.
isGoal (S _ al _ _) = al == []
事實上,還有一個標準函式(==[])
:
isGoal (S _ al _ _) = null al
或者,如果您覺得必須提及True
and False
,
isGoal (S _ [] _ _) = True
isGoal _ = False
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/493308.html
上一篇:如何從Test.QuickCheck顯式匯入“Fn”模式?
下一篇:創建haskel套接字客戶端