[英]How do I use if-then-else statement with no else condition in Haskell?
[英]How do I use if/then/else or guards in a case statement in Haskell?
“ Guards vs. If-Then-Else”有所幫助,但我仍然想知道這是否可以工作。 我需要獲取一個列表,然后返回列表的所有其他元素。 對於偶數長度列表,即使長度(xs) mod
2 == 1開始存在問題,我也明白了,所以我想分拆列表大小的初始長度,如下所示:
everyOther:: [Int] -> [Int]
everyOther [] = []
everyOther (x:xs) = case length (xs) 'mod' 2 of 0 ->
if (length (xs) `mod` 2 == 0)
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
1 -> if (length (xs) `mod` 2 == 1)
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
它告訴我“ if”處可能存在“間距錯誤”,但這在功能上是正確的。 我可以這樣做嗎?
這段代碼中似乎存在一些不同的錯誤,從語法到概念到算法,整個過程都在變化。 讓我們從語法錯誤開始,然后向上移動。
Haskell中的代碼被組織成塊。 塊的每個元素必須以相同的縮進級別開始; 對於初學者,嵌套塊應使用比其周圍的塊更深的縮進級別。 在頂層,模塊是一個塊,其元素為方程式。 case
/ of
也開始一個塊,其元素為pattern -> expression
match。
這些規則一起意味着, case
語句中的模式0
和1
應該彼此對齊,並且縮進的程度要比everyOther
的第一個e
縮進得多。 里面的表情應該更深一些以避免混淆。 這是滿足這些約束的一種流行樣式:
everyOther (x:xs) = case length (xs) 'mod' 2 of
0 -> if (length (xs) `mod` 2 == 0)
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
1 -> if (length (xs) `mod` 2 == 1)
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
下一步:反引號( `
-通常位於鍵盤頂部的數字行的左側)和正勾號( '
)在Haskell中含義不同。 使用反引號將前綴函數轉換為infix函數是很重要的。 所以length (xs) 'mod' 2
length (xs) `mod` 2
應該是length (xs) `mod` 2
。 您也有很多多余的括號,特別是關於length
的論點和if
表達式的代碼。 盡管不是錯誤,但是值得學習優先規則,因為您需要了解不會亂碼的代碼。
everyOther (x:xs) = case length xs `mod` 2 of
0 -> if length xs `mod` 2 == 0
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
1 -> if length xs `mod` 2 == 1
then x:everyOther (take 1 xs)
else x:everyOther (drop 1 xs)
接下來是一個概念上的錯誤。 在諸如case foo of 0 -> a; 1 -> b
這樣的表達式中case foo of 0 -> a; 1 -> b
case foo of 0 -> a; 1 -> b
,我們將僅在foo == 0
時評估表達式a
,並且僅在foo == 1
時評估表達式b
。 這樣可以使您的條件下的測試變得多余。 在case
兩個分支中,我們肯定會采用then
分支。 因此,如果我們按字面意義使用此代碼,則改為編寫以下代碼會更簡單且等效:
everyOther (x:xs) = case length xs `mod` 2 of
0 -> x:everyOther (take 1 xs)
1 -> x:everyOther (take 1 xs)
由於我們現在在case
兩個分支中都具有相同的代碼,因此顯然這不是您的意圖; 但是我不清楚你的意圖是什么。
還有另一個可疑的(盡管同樣,從技術上來講不是錯誤的 )細節:請記住,在everyOther (x:xs) = foo
的foo
everyOther (x:xs) = foo
,列表xs
不包括提供給everyOther
的列表的第一個元素。 因此,與給everyOther
的輸入長度相比,像length xs
類的調用將減少everyOther
。 在編寫case
語句的0
和1
模式的表達式時要考慮到這一點。
回到您的意圖:由於在兩種模式下您都編寫了everyOther (take 1 xs)
,因此我假設您希望有時對該表達式進行求值。 這使我認為您遇到算法錯誤; take 1 xs
將丟棄幾乎所有輸入列表,這與我對您要everyOther
要做的理解everyOther
。
希望本討論會指導您改進嘗試,並且可以在實現目標方面取得更大的進步。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.