我在编写笛卡尔幂函数时遇到问题。我发现了许多关于计算笛卡尔积的例子,但没有关于笛卡尔幂的例子
例如,[1; 2]上升到幂3 = [[1; 1; 1]; [1; 1; 2]; [1; 2; 1]; [1; 2; 2]; [2; 1; 1]; [2; 1; 2]; [2; 2; 1]; [2; 2; 2]]
我使用以下代码来计算笛卡尔积:
let Cprod U V =
let mutable res = []
for u in U do
for v in V do
res <- res @ [[u;v]]
res
试图计算笛卡尔的力量。 我使用以下代码来计算笛卡尔积:
let Cpower U n =
let mutable V = U
for i=0 to n-1 do
V <- Dprod U V
V
Visual Studio说:错误在统一''a'和''列表'时,结果类型将是无限的。我会感谢任何帮助和链接。
答案 0 :(得分:2)
至于错误的来源,我们有以下类型约束
// Cprod: seq<`a> -> seq<`a> -> `a list list
let Cprod U V =
...
// Cpower: seq<`a> -> int -> ???
let Cpower U n =
// V: seq<`a>
let mutable V = U
// n: int
for i=0 to n-1 do
(* The next line implies two type constraints:
V: seq<`a>
V: `a list list *)
V <- Dprod U V
V
V
必须是seq<`a>
和`a list list
,并且U和V必须具有相同的类型才意味着`a = `a list
,这就是“无限类型“错误消息(无限类型为... list list list list
。即使V
的值是可变的,它也必须是单一类型。
答案 1 :(得分:1)
这是从Haskell移植的版本:
let replicate n x = [for i in 1 .. n -> x]
let sequence ms =
List.fold (fun m' m -> [for x in m do for xs in m' -> (x::xs)]) [[]] ms
let Cpower n l = replicate n l |> sequence
它的作用类似于计数:如果您将l
视为数字,则会根据您拥有的地点数复制它们,然后使用sequence
计算它们。
换句话说,所有二进制数小于2 ^ 3都可以通过复制[0;1]
3次来生成[[0;1]; [0;1]; [0;1]]
然后再运行sequence
来生成。
切换到Seq.fold
:
let sequence' ms =
Seq.fold (fun m' m -> seq {for x in m do for xs in m' do yield (x::xs)})
(seq {yield []})
ms
这为您提供了结果的seq而不是列表。不幸的是,我不能通过查看它是否懒得足够:它可能必须在内存中生成整个列表以开始为您提供第一个元素。您应该能够通过在调试器中单步调试来找到它。 (或者你可能比我更善于阅读懒惰。)
答案 2 :(得分:1)
我还要补充一点,在编写F#代码时,通常最好避免使用mutable
值。当您学习F#或者需要优化某些代码以更快地运行时,这很好,但如果您想编写更加惯用的F#代码,最好使用递归而不是mutable
值。
我试着更优雅地写出笛卡尔的力量,这是我的版本。它是递归实现的。当我们需要计算X^1
并且递归案例执行像这样的笛卡尔积时,我明确地处理了这个案例:X^n = X * X^(n-1)
我正在使用序列表达式,该方法使用yield
生成序列的元素(作为结果返回):
let rec cartesianPow input n = seq {
if (n = 1) then
// This handles the case when the recursion terminates. We need to turn
// each element from the input into a list containing single element:
// [1; 2; 4] ^ 1 = [ [1]; [2]; [3] ]
for el in input do
yield [el]
else
// We perform one Cartesian product (and run the rest of the
// power calculation recursively). Mathematically:
// [1; 2; 3] ^ n = [1; 2; 3] x ([1; 2; 3] ^ (n-1))
for el in input do
for rest in cartesianPow input (n - 1) do
yield el :: rest }
cartesianPow [ 0; 1 ] 3
这不是最有效的实现(例如,因为在yield
循环中使用for
可能不是一件好事),但这对于大型n
来说只会出现问题。在F#中,通常最好从最容易理解的最干净的实现开始: - )。
答案 3 :(得分:0)
我解决了我的问题:
let rec Cprod = function
| [] -> [[]]
| hs::tss ->
[ for h in hs do
for ts in D tss ->
h::ts]
let Cpower U n =
let mutable inp = []
for i=0 to n-1 do
inp <- inp @ [U]
Dprod inp