簡體   English   中英

如何在Haskell的案例陳述中使用if / then / else或guards?

[英]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語句中的模式01應該彼此對齊,並且縮進的程度要比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) = foofoo everyOther (x:xs) = foo ,列表xs不包括提供給everyOther的列表的第一個元素。 因此,與給everyOther的輸入長度相比,像length xs類的調用將減少everyOther 在編寫case語句的01模式的表達式時要考慮到這一點。

回到您的意圖:由於在兩種模式下您都編寫了everyOther (take 1 xs) ,因此我假設您希望有時對該表達式進行求值。 這使我認為您遇到算法錯誤; take 1 xs將丟棄幾乎所有輸入列表,這與我對您要everyOther要做的理解everyOther

希望本討論會指導您改進嘗試,並且可以在實現目標方面取得更大的進步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM