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
这些列表我得到上面的错误。请解释为什么错误说 'Googol list -> Googol list'
在函数中,我是将函数作为参数插入到函数中,还是在连接后插入实际列表。 @
是函数吗?
您在这里缺少一个参数:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
^^^^^^^^^^^^^^^
here
powerInner
定义了三个参数,但您只传递了两个。
在 F# 中,传递少于定义的参数在技术上并不违法。如果这样做,结果将是一个“期望”剩余参数的函数。例如:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
因此,在您的情况下,省略最后一个参数会生成结果类型 Googol list -> Googol list
,然后证明它与运算符 @
期望的类型 Googol list
不兼容。这是编译器在错误消息中告诉您的内容。
这看起来像是家庭作业或练习,所以首先我会给出一些继续前进的提示。最后,我将展示一个似乎可行的版本,然后说明我将如何解决该问题。
任务是找到 a ** b
,对于 a
和 b
小于 100 的数字,其自身数字的总和最大。
第一个问题是float不会把a ** b
的所有数字都给我们,所以type没法解决这个问题。为了解决这个问题,我们求助于 BigInteger 类型和 BigInteger.Pow 函数。如果我们 运行 下面的代码片段,就像问题描述中所说的那样,我们会得到一个 1 后跟 200 个零。
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
要获得有用的结果,请更改 Googol 类型,使其使用 bigint
,但 power
除外,它应该是 int
。
为什么函数powerInner
和numberInner
在函数generatePowers
里面?这似乎没有特定目的,所以我建议将它们移出以使其更清楚。
函数 powerInner
对 n
进行匹配,但随后将结果命名为 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 函数可以以更实用的方式实现相同的目的。
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
这些列表我得到上面的错误。请解释为什么错误说 'Googol list -> Googol list'
在函数中,我是将函数作为参数插入到函数中,还是在连接后插入实际列表。 @
是函数吗?
您在这里缺少一个参数:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
^^^^^^^^^^^^^^^
here
powerInner
定义了三个参数,但您只传递了两个。
在 F# 中,传递少于定义的参数在技术上并不违法。如果这样做,结果将是一个“期望”剩余参数的函数。例如:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
因此,在您的情况下,省略最后一个参数会生成结果类型 Googol list -> Googol list
,然后证明它与运算符 @
期望的类型 Googol list
不兼容。这是编译器在错误消息中告诉您的内容。
这看起来像是家庭作业或练习,所以首先我会给出一些继续前进的提示。最后,我将展示一个似乎可行的版本,然后说明我将如何解决该问题。
任务是找到 a ** b
,对于 a
和 b
小于 100 的数字,其自身数字的总和最大。
第一个问题是float不会把a ** b
的所有数字都给我们,所以type没法解决这个问题。为了解决这个问题,我们求助于 BigInteger 类型和 BigInteger.Pow 函数。如果我们 运行 下面的代码片段,就像问题描述中所说的那样,我们会得到一个 1 后跟 200 个零。
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
要获得有用的结果,请更改 Googol 类型,使其使用 bigint
,但 power
除外,它应该是 int
。
为什么函数powerInner
和numberInner
在函数generatePowers
里面?这似乎没有特定目的,所以我建议将它们移出以使其更清楚。
函数 powerInner
对 n
进行匹配,但随后将结果命名为 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 函数可以以更实用的方式实现相同的目的。