Returning arrays of different dimensions from one function; is it possible in F#?

≡放荡痞女 提交于 2019-12-18 06:48:07

问题


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 floats
float[][] 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!