繁体   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