2015-10-20 58 views
0

我想模擬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函數。如果你願意,這是一個限制。

+2

你的第一個lambda是過分複雜的。它可以簡單地寫成'(\ list - >(length list)> a)',或者完全用'((> a)。length)'來完成,儘管很多人可能會發現後者很難閱讀。 – ApproachingDarknessFish

+2

'seq'對用戶定義的函數來說是一個非常不恰當和令人困惑的名字:它也作爲原始函數/運算符存在,用於強制評估其他懶惰的thunk。另外,不要使用「序列」,因爲測序具有特殊而廣泛的含義。 –

回答

5

我認爲這一個不錯的解決方案是不嘗試恢復「我們還需要做多少步驟」,從列表構建,而是使用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) 
+0

謝謝!我發現如何解決這個問題:) –

0

感謝您的答覆。我找到了解決它的另一種方法:

seq :: Int -> [Int]  
seq a = until (\l -> (length l) >= a) (\x -> x ++ [((last x) + 1)]) [1] 
+3

Dr.「Cactus」Erdi的方法既簡單又高效。你應該研究它並思考爲什麼。 – dfeuer