"Guards vs. If-Then-Else"帮助了一点,但我仍然想知道这是否可以以某种方式起作用.我需要获取一个列表并返回列表中的每个其他元素.对于偶数长度列表,我得到它只是如果长度(xs)mod2 == 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)
Run Code Online (Sandbox Code Playgroud)
它告诉我"if"可能存在"间距错误",但这在功能上是正确的.我可以这样做吗?
在这段代码中似乎存在一些不同的错误,从语法到概念到算法的整个范围都有所不同.让我们从语法错误开始,向上移动链.
Haskell中的代码被组织成块.块的每个元素必须以相同的缩进级别开始; 对于初学者,嵌套块应使用比其周围块更深的缩进级别.在顶层,模块是一个块,其元素是方程式.case/ of也开始一个块,其元素是pattern -> expression匹配的.
总之,这些规则意味着模式0和1你的case陈述应相互对齐和缩进比第一更深e的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)
Run Code Online (Sandbox Code Playgroud)
下一步:反引号(`- 通常位于键盘顶部数字行的左侧)和前向ticks(')表示Haskell中的不同内容.使用反引号将前缀函数转换为中缀函数非常重要; 所以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)
Run Code Online (Sandbox Code Playgroud)
接下来是概念错误.在类似的表达式中case foo of 0 -> a; 1 -> b,我们只会a在何时评估表达式foo == 0,并且只会b在何时评估表达式foo == 1.这使得您的条件下的测试变得多余; 在两个分支中case,我们一定会采取then分支机构.因此,如果我们按字面意思理解这些代码,那么编写此代码会更简单和等效:
everyOther (x:xs) = case length xs `mod` 2 of
0 -> x:everyOther (take 1 xs)
1 -> x:everyOther (take 1 xs)
Run Code Online (Sandbox Code Playgroud)
既然我们现在在两个分支中都有相同的代码case,那么很明显这不是你的意图; 但我不清楚你的意图是什么.
还有一种可疑的(虽然再次,不是技术上的错误)详情:请记住,在foo中everyOther (x:xs) = foo,名单xs不包括给列表的第一个元素everyOther.因此length xs,与给定的输入长度相比,调用类似于一个调用everyOther.在为语句的模式0和1模式编写表达式时,请考虑到这一点case.
回到你的意图:因为在你编写的两种模式中everyOther (take 1 xs),我认为你有时需要对该表达式进行评估.这让我觉得你有一个算法错误; take 1 xs将丢弃几乎所有的输入列表,这与我对你想做everyOther的事情的理解不符.
希望这个讨论可以指导您改进尝试,并且可以在实现目标方面取得更多进展.