Haskell使用“until”函数模拟[1 .. n]
我想模拟Haskell中的[1 .. n]
功能,但使用until
函数。我想要做这样的事情:Haskell使用“until”函数模拟[1 .. n]
seq :: Int -> [Int]
seq a = until (\list -> if (length list) > a then True else False) (\x -> x ++ ((tail x) + 1)) [1]
,并通过调用seq 5
它应该返回[1, 2, 3, 4, 5]
。我必须使用until
函数。如果你愿意,这是一个限制。
我认为这一个不错的解决方案是不尝试恢复“我们还需要做多少步骤”,从列表构建,而是使用until
上的一对列表和数量添加剩余的元素:
(5, []) ->
(4, 5:[]) = (4, [5]) ->
(3, 4:[5]) = (3, [4, 5]) ->
(2, 3:[4, 5]) = (2, [3, 4, 5]) ->
(1, 2:[3, 4, 5]) = (1, [2, 3, 4, 5]) ->
(0, 1:[2, 3, 4, 5]) = (0, [1, 2, 3, 4, 5])
注意,当剩余元件的数量是0,即正好意味着我们已经构建列表是一个我们之后。
因此,我们可以实现这个想法通过做一个until
了一对,检查是否对的第一个元素是等于0,以决定是否我们已经完成:
seq0 :: Int -> (Int, [Int])
seq0 n = until (\(i, is) -> i == 0) (\(i, is) -> (i-1, i:is)) (n, [])
当然,这将返回全对(0, [1..n])
,所以我们只需要保留一对的第二个元素:
seq :: Int -> [Int]
seq n = snd (seq0 n)
谢谢!我发现如何解决这个问题:) –
感谢您的答复。我找到了解决它的另一种方法:
seq :: Int -> [Int]
seq a = until (\l -> (length l) >= a) (\x -> x ++ [((last x) + 1)]) [1]
Dr.“Cactus”Erdi的方法既简单又高效。你应该研究它并思考为什么。 – dfeuer
你的第一个lambda是过分复杂的。它可以简单地写成'(\ list - >(length list)> a)',或者完全用'((> a)。length)'来完成,尽管很多人可能会发现后者很难阅读。 – ApproachingDarknessFish
'seq'对用户定义的函数来说是一个非常不恰当和令人困惑的名字:它也作为原始函数/运算符存在,用于强制评估其他懒惰的thunk。另外,不要使用“序列”,因为测序具有特殊而广泛的含义。 –