F #: обернуть один элемент в массив - PullRequest
0 голосов
/ 21 июня 2011

в 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 ]

4 голосов
/ 21 июня 2011

Кажется, что работает следующее:

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>>.

В ответ на ваш комментарий: подобные вещи могут быть выполнены в статически типизированных языках.и, возможно, лучше, чем в динамическом языке, но / потому что выход за пределы системы типов должен быть явным (например, box / unbox).

2 голосов
/ 21 июня 2011

Вот решение на основе отражения, которое будет принимать входные данные произвольной глубины вложенного массива:

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|]|]
1 голос
/ 21 июня 2011

Вы не можете, это не типизированная функция (попробуйте выписать сигнатуру типа).

0 голосов
/ 22 июня 2011

Ваша функция должна "обернуть любые входные данные в массив массива".Как и в этом утверждении, решение простое:

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

Но тогда приведенные вами примеры не соответствуют определению вашей функции.то есть wrapper([|1|]) = [|[|1|]|] должно быть wrapper([|1|]) = [|[|[|1|]|]|] в соответствии с определением вашей функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...