Предупреждение пространства имен F# 2.0

Я просто установил последнюю версию F# и открыл старое решение видеть то, что это скажет мне.

Это - многофайловое решение, где первый файл включает некоторые 'дополнительные функции' в модуль Списка:

module List = 
    ///Given list of 'rows', returns list of 'columns' 
    let rec transpose lst =
        match lst with
        | (_::_)::_ -> List.map List.hd lst :: transpose (List.map List.tl lst)
        | _         -> []

Компилятор больше не любит это и говорит:

Файлы в библиотеках или приложениях нескольких-файлов должны начаться с пространства имен или объявления модуля, например, 'пространства имен SomeNamespace. SubNamespace' или 'модуль SomeNamespace. SomeModule'

Но если я делаю это:

module Foo.List = 

Это говорит:

Сокращение модуля должно быть простым именем, не путем

Что я пропускаю здесь? И каково решение для этого 'специального' случая, где я расширяю модуль, который прибывает откуда-либо?

8
задан Benjol 12 February 2010 в 07:27
поделиться

1 ответ

Во-первых, вы имеете в виду «typedef», а не «typecast» в вашем вопросе.

В C указатель на тип T может указывать на объект типа T :

int *pi;
int i;
pi = &i;

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

int a[3];
int *pa = a;

Но для полноты: в присвоении имя a эквивалентно & a [0] , т.е. указатель на первый элемент массива a . Если вы не уверены в том, как и почему это работает, есть много ответов, объясняющих, когда именно имя массива «распадается» на указатель, а когда нет:

Я уверен, что есть еще много таких вопросов и ответов на SO, я только что упомянул некоторые, что я нашел из поиска.

Вернемся к теме

int foo[2][4];

foo имеет тип «массив [2] массива [3] int ». Это означает, что foo [0] является массивом 3 int s, а foo [1] является массивом 3 int s.

Теперь предположим, что мы хотим объявить указатель, и мы хотим присвоить его foo [0] . То есть мы хотим сделать:

/* declare p somehow */
p = foo[0];

Вышеуказанное не отличается по форме от int * pa = a; , потому что типы a и foo [0] одинаковы. Итак, нам нужно int * p; как наше объявление p .

Главное, что нужно помнить о массивах, это то, что «правило» о затухании имени массива до указателя на его первый элемент применяется только один раз. Если имеется массив массива, то в контекстах значений имя массива будет распадаться не на тип «указатель на указатель», а на тип «указатель на массив». Возвращаясь к foo :

/* What should be the type of q? */
q = foo;

Имя foo выше является указателем на первый элемент foo , т.е. можно записать выше как:

q = &foo[0];

Тип foo [0] является «array [3] of int ». Поэтому нам нужно, чтобы q был указателем на «массив [3] из int »:

int (*q)[3];

Скобки вокруг q необходимы, потому что [] связывается более плотно, чем * в C, поэтому int * q [3] объявляет q как массив int * (q [3]) - это, сверху, эквивалент int * q [3] , т.е. массив 3 указателей на int .

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

О чтении деклараций вообще: вы читаете их "наизнанку", начиная с имени "переменной" (если она есть). Вы идете налево как можно больше, если нет [] непосредственно справа, и вы всегда соблюдаете круглые скобки. cdecl должен в какой-то степени помочь:

$ cdecl
cdecl> declare p as  pointer to array 3 of int
int (*p)[3]
cdecl> explain int (*p)[3]
declare p as pointer to array 3 of int

Читать

int (*a)[3];

      a            # "a is"
    (* )           # parentheses, so precedence changes.
                   # "a pointer to"
        [3]        # "an array [3] of"
int        ;       # "int".

Для

int *a[3];

     a             # "a is"
      [3]          # "an array [3] of"
    *              # can't go right, so go left.
                   # "pointer to"
int      ;         # "int".

Для

char *(*(*a[])())()

          a         # "a is"
           []       # "an array of"
         *          # "pointer to"
        (    )()    # "function taking unspecified number of parameters"
      (*        )   # "and returning a pointer to"
                 () # "function"
char *              # "returning pointer to char"

(Пример из c-faq вопрос 1,21 . На практике, если вы читаете такое сложное заявление, с кодом что-то серьезно не так!)

-121--1586566-

явно преобразовать его в int first

(<= 0x20 (int current) 0xD7FF)
-121--3941991-

Сделать пространство имен явным:

namespace Microsoft.FSharp.Collections

module List =  
    ///Given list of 'rows', returns list of 'columns'  
    let rec transpose lst = 
        match lst with 
        | (_::_)::_ -> List.map List.head lst :: transpose (List.map List.tail lst) 
        | _         -> []

Обратите внимание, что List.hd и List.tl были переименованы в List.head и List.tail

6
ответ дан 5 December 2019 в 22:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: