[英]haskell: factors of a natural number
我正在嘗試在Haskell中編寫一個函數,該函數計算給定數字以外的所有因子。
結果應如下所示:
factorlist 15 => [1,3,5]
我是Haskell和整個遞歸主題的新手,我很確定我可以在此示例中應用它,但是我不知道在哪里或如何使用。
我的想法是使用mod
函數將給定數字與1到n div
2列表中的第一個元素進行比較,但是以某種方式遞歸進行比較,如果結果為0
則將數字添加到新列表中。 (我希望這有道理)
我將不勝感激
到目前為止,這是我的代碼:(它不起作用..但是以某種方式說明了我的想法)
factorList :: Int -> [Int]
factorList n |n `mod` head [1..n`div`2] == 0 = x:[]
有幾種方法可以解決此問題。 但首先,讓我們寫一個小的小助手:
isFactorOf :: Integral a => a -> a -> Bool
isFactorOf x n = n `mod` x == 0
這樣,我們可以將12 `isFactorOf` 24
寫入True
或False
。 對於遞歸部分,假設我們使用一個帶有兩個參數的函數:一個是我們要分解的數字,第二個是我們目前正在測試的因子。 我們僅測試n `div` 2
或等於n `div` 2
因子,這將導致:
createList n f | f <= n `div` 2 = if f `isFactorOf` n
then f : next
else next
| otherwise = []
where next = createList n (f + 1)
因此, 如果第二個參數是n
的因數,則將其添加到列表中並繼續,否則就繼續。 只要f <= n `div` 2
我們就這樣做。 現在,為了創建factorList
,我們可以簡單地使用createList
有足夠的第二個參數:
factorList n = createList n 1
遞歸隱藏在createList
。 因此, createList
是工人 ,你可以把它藏在一個where
的內部factorList
。
請注意,可以使用過濾器或列表factorList
輕松定義factorList
:
factorList' n = filter (`isFactorOf` n) [1 .. n `div` 2]
factorList'' n = [ x | x <- [1 .. n`div` 2], x `isFactorOf` n]
但是在這種情況下,您自己不會編寫遞歸。
filter
功能。 @Zeta的答案很有趣。 但是,如果您像我一樣是Haskell的新手,那么您可能希望以一個“簡單”的答案開始。 (只是獲得基本的遞歸模式...並了解縮進以及類似的內容。)
我不會將任何東西除以2,而是將數字本身包括在內。 因此,在我的示例中, factorlist 15 => [1,3,5,15]
:
factorList :: Int -> [Int]
factorList value = factorsGreaterOrEqual 1
where
factorsGreaterOrEqual test
| (test == value) = [value]
| (value `mod` test == 0) = test : restOfFactors
| otherwise = restOfFactors
where restOfFactors = factorsGreaterOrEqual (test + 1)
第一行是類型簽名,您已經知道。 類型簽名不必位於函數的模式定義列表的旁邊 (盡管模式本身需要在順序行上全部組合在一起)。
然后,根據輔助函數定義factorList
。 此輔助函數在where
子句中定義...表示這是局部函數, 可以訪問value參數 。 如果我們全局定義factorGreaterOrEqual,那么它將需要兩個參數,因為value不在范圍內,例如
factorsGreaterOrEqual 4 15 => [5,15]
您可能會說,factorsGreaterOrEqual本身就是一個有用的函數。 也許是,也許不是。 但是在這種情況下,我們要說的是除了幫助我們定義factorList
以外,它不是一般用途...因此使用where子句並隱式地獲取值更干凈。
從我的角度來看,Haskell的縮進規則很奇怪,但是這里對它們進行了總結 。 我在這里縮進兩個空格,因為如果使用4,它會增長得太遠。
在Haskell中,前面帶有該豎線字符的布爾測試列表稱為“守衛”。 我只是將最終條件設置為測試達到值時的狀態。 因此,如果我們正在調用factorList N
則factorsGreaterOrEqual N = [N]
。 然后,我們通過將值除以沒有余數來決定是否將測試號連接到列表中。 ( otherwise
為Haskell關鍵字,對於掉線default
,類似C的switch語句中的default
)
為了展示另一個層次的嵌套和另一個隱式參數演示,我添加了一個where子句以本地定義一個名為restOfFactors
的函數。 無需將test作為參數傳遞給restOfFactors,因為它位於“ factorsGreaterOrEqual
”的范圍內...並且因為它位於factorList
的范圍內, factorList
值也可用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.