你混合當務之急和功能範例:let n = 0
,let (x:xs) = (x:xs) ++ (x:xs)!!n
,arg = arg - 1
,n = n + 1
是(在你的代碼)勢在必行表達式。您期望修改n
,(x:xs)
和arg
的值,但函數式編程不能像那樣工作。
你聲明的功能是爲了純:這意味着你不能期望值被修改(我們稱之爲「副作用」)。你唯一能做的就是用新的參數調用一個新的函數(或者相同的函數),這些新的參數是從原始參數「實時」計算出來的。
讓我們試着具體。
你不能做:
arg = arg - 1
demo arg (x:xs)
但你可以這麼做:
demo (arg - 1) (x:xs)
後者是demo
與arg - 1
作爲參數調用。 arg
的值從未修改過。
代碼中的主要問題是n
變量。在第一次調用時它應該是0
,並且應該每次增加arg < length (x:xs)
以將來自(x:xs)
的下一個元素添加到(x:xs)
本身的末尾。因此,該列表將以循環方式增長,直到我們可以獲得所需數量的元素。
爲了達到這個目標,你必須創建一個輔助功能和「移動」的遞歸成輔助功能:
demo :: Int -> [a] -> [a]
demo arg [] = []
demo arg (x:xs) = demo' arg 0 (x:xs) -- n = 0
where
demo' :: Int -> Int -> [a] -> [a]
demo' arg n l = if arg <= length l
then take arg l
else
-- call demo' with new parameters:
-- (x:xs) = (x:xs) ++ [(x:xs)!!n]
-- arg = arg - 1
-- n = n + 1
demo' (arg-1) (n+1) ((x:xs) ++ [(x:xs)!!n]) ```
現在,從你給的例子,arg
是的常數您要創建的列表中的元素,所以不應該減少。而且你不需要解構(x:xs)
中的列表。最後,一點點清理,您有:
demo :: Int -> [a] -> [a]
demo arg [] = []
demo arg l = demo' arg 0 l
where
demo' :: Int -> Int -> [a] -> [a]
demo' arg n l = if arg <= length l
then take arg l
else demo' arg (n+1) (l ++ [l!!n])
有一種更好的方法來實現這一(demo n=take n.cycle
),但我想貼近你原來的執行。
'可能不正確的縮進'。 'let..in'塊看起來不正確的縮進。嘗試嘗試縮進以獲取代碼進行編譯。 –
'let arg = arg-1'和'let n = n + 1'是遞歸定義,定義'arg'和'n'爲無限循環計算。你不想那樣。你正在試圖改變Haskell中的變量,這是爲了讓這個變得不可能。這種方法對於在FP語言中工作來說太過緊迫。粗略地說,「改變」一個變量的唯一方法是用新值調用一個函數,例如。 'f 0 = 0; f n = f(n-1)'定義了一個遞歸,「遞減」n直到它達到0. – chi