簡體   English   中英

f# 連接對象列表

[英]f# concatenate list of objects

type Googol = {
    number : float
    power : float
    result : float
}

let generatePowers (n:float) : list<Googol> = 
    let rec powerInner (n:float) (p:float) (acc : list<Googol>) = 
        match n with
        | p when p <= 1.0 -> acc
        | p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]@acc)
    let rec numberInner (n:float) (acc : list<Googol>) = 
        match n with 
        | n when n <=1.0 -> acc
        | n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
    numberInner n []

ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
    'Googol list'
but here has type
    'Googol list -> Googol list'

我正在嘗試解決這個問題-> https://projecteuler.net/problem=56 | 但為此我需要生成低於 n < 100 的冪。當我嘗試連接[{ number=n; power=p; result=n**p}]@acc [{ number=n; power=p; result=n**p}]@acc [{ number=n; power=p; result=n**p}]@acc這些列表我得到了上面的錯誤。 請解釋為什么錯誤顯示'Googol list -> Googol list'在 function 中,我是否將 function 作為參數插入 ZC1C425268E68385D1AB4074C17A94 或實際插入列表之后。 @是function嗎?

您在這里缺少一個參數:

| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
                                         ^^^^^^^^^^^^^^^
                                               here

powerInner用三個參數定義,但你只傳遞了兩個。

在 F# 中,傳遞比定義少的參數在技術上並不違法。 如果這樣做,結果將是“預期”剩余參數的 function。 例如:

let f : int -> int -> string

let x = f 42
// Here, x : int -> string

let y = x 5
// Here, y : string

因此,在您的情況下,省略最后一個參數會使結果類型Googol list -> Googol list ,然后結果與 operator @預期的類型Googol list不兼容。 這是編譯器在錯誤消息中告訴您的內容。

這看起來像是家庭作業或練習,所以首先我會給出一些提示以繼續前進。 最后,我將展示一個似乎可以工作的版本,然后告訴我將如何解決這個問題。

任務是找到數字a ** b ,對於ab小於 100,其自身數字的總和最大。

第一個問題是 float 不會給我們a ** b的所有數字,所以這種類型對解決問題沒有用處。 為了解決這個問題,我們轉向 BigInteger 類型和 BigInteger.Pow function。 然后如果我們運行以下代碼段,我們會得到一個 1 后跟 200 個零,就像它在問題描述中所說的那樣。

let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x

要獲得有用的結果,請更改 Googol 類型,使其使用bigint ,但power應該是int

為什么 function generatePowers里面的函數powerInnernumberInner 這似乎沒有特定目的,因此我建議將它們移出以使其更清楚。

function powerInnern進行匹配,但隨后將結果命名為p ,這會隱藏p參數,使其未被使用。 好的,這里的意圖可能是匹配p而不是n ,所以只需修復它,然后p參數的陰影就很好了。

首先在<= 1上然后在> 1上的測試會導致不完整的匹配。 如果第一行檢查數字是否小於或等於 1,則在下一行中它必須大於 1。 因此,只需使用n ->而無需when修復它。 我還懷疑您想測試<= 0而不是 1。

這個

[{ number=n; power=p; result=n**p}]@acc

可以只是

{ number=n; power=p; result=n**p } :: acc

和這里

(powerInner n [])

我懷疑你只需要一個功率的起始值,即 99

(powerInner n 99 [])

劇透警告

經過一番修補,這就是我最終得到的,它似乎打印出一個有用的數字列表。 請注意,為了不通過打印輸出運行所有 99 x 99 結果,我在這里使用低起始數字 3 和 5 進行倒計時,所以我們得到一些簡單的打印輸出,我們可以研究分析。

type Googol = { number: bigint; power: int; result: bigint }

let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
    match p with
    | p when p <= 0 -> acc
    | p ->
        let newNumber = { number = n; power = p; result = n ** p }
        printfn "newNumber=%0A" newNumber
        powerInner n (p - 1) (newNumber :: acc)

let rec numberInner (n: bigint) (acc: Googol list) =
    match n with
    | n when n <= 0I -> acc
    | n -> numberInner (n - 1I) ((powerInner n 5 []) @ acc)

let generatePowers (n: bigint) : Googol list =
    numberInner n []

let powers = generatePowers 3I

我不確定這個解決方案是否正確。 無論如何,我會做不同的事情。

我會簡單地在兩個循環中循環 a 和 b,一個在另一個循環中。 對於每個a ** b我會將結果轉換為字符串,然后對字符串的數字求和。 然后我會簡單地使用一個可變的來保持最高的結果。 使用其中一個花哨的 List 函數可以以更實用的方式實現相同的目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM