如果這不是功課:let (ys,zs) = splitAt n xs in ys ++ [new_element] ++ zs
對於此文章中,我將假設你正在做的這個問題,因爲功課或教自己如何做這種事情的其餘部分。
這種問題的關鍵是把它分解成它自然的情況。您正在處理兩條數據:您要插入的列表以及該列表中的位置。在這種情況下,每一條數據都有兩個自然情況:您處理的列表可以是空或不是,您正在處理的數字可以是零或不是。所以第一步是寫出來的所有四種情況:
insertAt 0 val [] = ...
insertAt 0 val (x:xs) = ...
insertAt n val [] = ...
insertAt n val (x:xs) = ...
現在,每一個的這四種情況下,你需要思考的答案應該給什麼,你在這種情況下是。
對於前兩種情況,答案很簡單:如果您想插入列表的前面,只需在開始處粘貼您感興趣的值,無論列表是否爲空。
第三種情況表明,問題實際上存在一個模棱兩可的問題:如果要求您插入空的列表的第三個位置,會發生什麼?聽起來對我來說是一個錯誤,但你必須爲自己回答你想要做的事情。
第四種情況非常有趣:假設您想要將值插入非空列表的非首位。在這種情況下,請記住,您可以使用遞歸來解決問題的較小實例。在這種情況下,您可以使用遞歸來解決,例如,insertAt (n-1) val xs
- 也就是將相同的值插入到輸入列表的尾部n-1
th位置的結果。例如,如果您嘗試將5插入列表[100,200,300]
的位置3(第四位置),則可以使用遞歸將5插入列表[200,300]
的位置2(第三位置),這意味着遞歸調用將生成[200,300,5]
。
我們可以只是假設遞歸調用將工作;我們現在唯一的工作就是將答案轉化爲解決原來問題的答案。我們在這個示例中想要的答案是[100,200,300,5]
(將5插入列表[100,200,300]
的位置4的結果,我們擁有的是列表[200,300,5]
。那麼我們如何才能得到我們想要的結果?只需在第一個元素上加上! (想想爲什麼這是真的。)
在這種情況下,我們已經涵蓋了列表和位置組合更新的所有可能情況。由於我們的功能將正確地適用於所有可能性,並且我們的可能性涵蓋所有可能性可能的輸入,這意味着我們的功能將始終正常工作,所以我們完成了!所以我們完成了!
我會留給你來把這些想法翻譯成Haskell,因爲練習的目的是讓你學習它,但希望那可以讓你知道如何解決問題。