![](/img/trans.png)
[英]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.