你如何在haskell中有多个语句?
这就是我要做的事情:给定一个像[a,b,c,d]这样的列表,返回其他所有元素,这样你得到[a,c]。我可以看到解决方案,这是我到目前为止所拥有的:
fact (xs) | length( xs ) `mod` 2 == 1 = head( xs )
| otherwise = fact(tail( xs ))
这在第一次工作正常,但随后退出。我想说的是返回头部,然后调用fact(tail(xs))我该怎么做?
答案 0 :(得分:15)
您指定的函数仅返回单个元素。您需要将其更改为:
fact [] = [] -- can't call tail on a list of length 0!
fact (xs) | length( xs ) `mod` 2 == 1 = head( xs ) : fact(tail(xs))
| otherwise = fact(tail( xs ))
您可能会发现写出类型签名有助于找出像这样的思想:
fact :: [a] -> [a] -- convert a list of anything to another (shorter) list
然而请注意,这非常慢 - 实际上是O(n ^ 2),因为它在每一步都需要很长时间。更多haskelly解决方案将使用模式匹配来一次处理两个元素:
fact :: [a] -> [a]
-- Take the first element of each two-element pair...
fact (x:_:xs) = x:fact xs
-- If we have only one element left, we had an odd-length list.
-- So grab the last element too.
fact [x] = [x]
-- Return nothing if we have an empty list
fact _ = []
答案 1 :(得分:14)
Haskell中没有任何陈述。
你不应该滥用Haskell中的括号。相反,你应该习惯自己的语言。所以你原来的代码应该是
fact xs | length xs `mod` 2 == 1 = head xs
| otherwise = fact (tail xs)
正如bdonlan所说,你正在寻找的功能真的是
fact [] = []
fact [x] = [x]
fact (x:_:xs) = x : fact xs
假设我们有列表[a, b, c, d]
。让我们应用该函数并完全评估结果。
fact [a, b, c, d] = a : fact [c, d]
= a : c : fact []
= a : c : []
= [a, c]
请注意[a, b, c, d]
与a : b : c : d : []
完全相同,因为编译器可以互换地解释表示列表的两种方式。
答案 2 :(得分:3)
事实上,我们可以遵循两种可能的模式:
两者都做同样的事情,但他们以相反的方式“开始计算”。让我们用相同的功能实现它们!当然,必须根据“模式”对该函数进行参数化。存在两种可能的模式,因此,我们需要一个用于参数化的类型的布尔值。实现:让我们使用布尔参数作为“标志”,“信号量”:
module Alternation where
every_second :: [a] -> [a]
every_second = every_second_at False
every_second_at :: Bool -> [a] -> [a]
every_second_at _ [] = []
every_second_at True (x : xs) = x : every_second_at False xs
every_second_at False (x : xs) = every_second_at True xs
我们使用了一个辅助功能,记下“flag / semaphore”:它相应地交换它。实际上,这个辅助功能可以看作是原始任务的概括。我认为,这就是所谓的“worker wrapper”功能。
任务可以进一步推广。为什么不编写更通用的函数,可以通过“modulus” m 进行参数化,并“收获”所有 m th 列表中的元素?
我们可以使用与以前相同的想法,只需要使用更复杂的“信号量”:自然数而不是布尔值。这是一个“倒计时”参数,一个索引 i 记录在轮到我们时:
module Cycle where
import Nat (Nat)
every_mth :: Nat -> [a] -> [a]
every_mth 0 = undefined
every_mth m @ (i + 1) = every_mth_at m i
我们使用辅助功能(worker wrapper),记录倒计时索引 i :
every_mth_at :: Nat -> Nat -> [a] -> [a]
every_mth_at _ _ [] = []
every_mth_at m 0 (x : xs) = x : every_mth m xs
every_nth_at m (i + 1) (x : xs) = every_mth_at m i xs
为简单起见,自然数字类型在这里被“实现”仅仅是别名:
module Nat (Nat) where
type Nat = Integer
也许,从理论上讲,还有更清晰的替代方法,并不完全等同于你指定的任务,但调整似乎很简单:
every_mth 1 [0,1,2,3,4,...]
收益[0,1,2,3,4,...]
every_mth 2 [0,1,2,3,4,...]
收益[0,2,4,6,8...]
every_mth 3 [0,1,2,3,4,...]
收益[0,3,6,9...]
因此,它在这里指定,以便当应用于所有自然数的惰性列表时,它应该“偶然”提供参数的倍数列表。
在其实施中,值得使用数字作为“从零开始”的索引。我们说:“使用 i 作为0,1,...,的索引,而不是”每个 m th “。 u = m -1,其中 u 表示可能索引的上限。这个上部索引可以是辅助函数中的一个有用参数,下来指数。
module Multiple where
import Nat (Nat)
every_mth :: Nat -> [a] -> [a]
every_mth 0 = undefined
every_mth (u + 1) = countdown u
countdown :: Nat -> [a] -> [a]
countdown = countdown_at 0
countdown_at :: Nat -> Nat -> [a] -> [a]
countdown_at _ _ [] = []
countdown_at 0 u (x : xs) = x : countdown_at u u xs
countdown_at (i + 1) u (x : xs) = countdown_at i u xs