F#:将单个元素包装到数组中

时间:2011-06-21 18:14:20

标签: f#

在F#中,如何使函数wrapper (x:'T)将任何输入包装到数组数组中,比如:wrapper(1) = [|[|1|]|]; wrapper([|1|]) = [|[|1|]|]; and wrapper([|[|1|]|]) = [|[|1|]|];类似下面的内容不起作用:

let wrapper (x:'T) = 
    let y = 
        if not <| x.GetType().IsArray then [|[|x|]|]
        elif not <| x.[0].GetType().IsArray then [|x|]
        else x
    y

4 个答案:

答案 0 :(得分:4)

以下似乎有效:

let wrapper<'a, 'b> (x:'a) = 
  match box x with
  | null -> null
  | :? array<array<'b>> as y -> y
  | :? array<'b> as y -> [|y|]
  | y -> [|[|unbox y|]|]

签名为'a -> array<array<'b>>

回应你的评论:这种事情可以用静态类型语言完成 - 并且可以说比动态语言更好 - 但是/因为在类型系统之外的步进必须是明确的(例如,{{ 1}} / box)。

答案 1 :(得分:2)

这是一个基于反射的解决方案,它将接受任意嵌套数组深度的输入:

open System.Text.RegularExpressions
let wrapper input =
    let ty = input.GetType()
    if ty.IsArray |> not then
        [|[|input |> unbox|]|]
    else
        let depth = Regex.Matches(ty.Name, "\[\]", RegexOptions.Compiled).Count
        let rec findInnerItem curDepth curArray =
            let innerItem = curArray.GetType().GetMethod("Get").Invoke(curArray, [|box 0|])
            if curDepth = depth then
                innerItem
            else
                findInnerItem (curDepth+1) innerItem

        let innerItem = findInnerItem 1 input
        [|[|innerItem |> unbox|]|]

FSI中的用法:

val wrapper : 'a -> 'b [] []

> let x : int[][] = wrapper 1;;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|1|];;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|[|1|]|];;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|[|[|1|]|]|];;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|[|[|[|1|]|]|]|];;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|[|[|[|[|1|]|]|]|]|];;

val x : int [] [] = [|[|1|]|]

> let x : int[][] = wrapper [|[|[|[|[|[|1|]|]|]|]|]|];;

val x : int [] [] = [|[|1|]|]

答案 2 :(得分:1)

你不能,这不是一个很好的类型的函数(尝试写出类型签名)。

答案 3 :(得分:-1)

您的功能需要“将任何输入包装到数组数组中”。与此声明相同,解决方案非常简单:

let wrapper (x:'T) = [|[|x|]|];

但是你给出的例子不是你的函数定义。 即wrapper([|1|]) = [|[|1|]|]应该wrapper([|1|]) = [|[|[|1|]|]|]与您的函数定义相同。