问题
I am trying to convert some Python to F#, specifically numpy.random.randn.
The function takes a variable number of int arguments and returns arrays of different dimensions based on the number of arguments.
I believe that this is not possible because one cannot have a function that returns different types (int[]
, int[][]
, int[][][]
, etc.) unless they are part of a discriminated union, but want to be sure before committing to a workaround.
The sanity check:
member self.differntarrays ([<ParamArray>] dimensions: Object[]) =
match dimensions with
| [| dim1 |] ->
[|
1
|]
| [| dim1; dim2 |] ->
[|
[| 2 |],
[| 3 |]
|]
| _ -> failwith "error"
causes error:
This expression was expected to have type
int
but here has type
'a * 'b
with the expression
being : [| 2 |], [| 3 |]
and the int
referring to the 1 in [| 1 |]
i.e. the type of 1
is not the same as the type of [| 2 |], [| 3 |]
TLDR;
numpy.random.randn
numpy.random.randn(d0, d1, ..., dn)
Return a sample (or samples) from the “standard normal” distribution.
If positive, int_like or int-convertible arguments are provided, randn generates an array of shape (d0, d1, ..., dn), filled with random floats sampled from a univariate “normal” (Gaussian) distribution of mean 0 and variance 1 (if any of the d_i are floats, they are first converted to integers by truncation). A single float randomly sampled from the distribution is returned if no argument is provided.
Examples from interactive python session:
np.random.randn(1) - array([-0.28613356])
np.random.randn(2) - array([-1.7390449 , 1.03585894])
np.random.randn(1,1)- array([[ 0.04090027]])
np.random.randn(2,3)- array([[-0.16891324, 1.05519898, 0.91673992],
[ 0.86297031, 0.68029926, -1.0323683 ]])
The code is for Neural Networks and Deep Learning and since the values need to mutable for performance reasons, using immutable list is not an option.
回答1:
You are correct - an array of floats float[]
is a different type than array of arrays of floatsfloat[][]
or 2D array of floats float[,]
and so you cannot write a function that returns one or the other depending on the input argument.
If you wanted to do something like the Python's rand
, you could write an overloaded method:
type Random() =
static let rnd = System.Random()
static member Rand(n) = [| for i in 1 .. n -> rnd.NextDouble() |]
static member Rand(n1, n2) = [| for i in 1 .. n1 -> Random.Rand(n2) |]
static member Rand(n1, n2, n3) = [| for i in 1 .. n1 -> Random.Rand(n2, n3) |]
回答2:
Although Tomas' suggestion to use overloading is probably best, .NET arrays do share a common sub-type: System.Array
. So what you want is possible.
member self.differntarrays ([<ParamArray>] dimensions: Object[]) : Array =
match dimensions with
| [| dim1 |] ->
[|
1
|] :> _
| [| dim1; dim2 |] ->
[|
[| 2 |],
[| 3 |]
|] :> _
| _ -> failwith "error"
来源:https://stackoverflow.com/questions/34599909/returning-arrays-of-different-dimensions-from-one-function-is-it-possible-in-f