F#, пространства имен, модули, fs и fsx

Мне известны другие вопросы о модулях и пространствах имен в F#, но они мне сейчас не помогают.

У меня есть проект с

Utilities.fs

namespace Company.Project.Namespace
module Utilities = 
     //stuff here

Functions.fs

namespace Company.Project.Namespace
open Utilities

module Functions = 
     //stuff here

И я пытаюсь проверить их в fsx:

#load "Utilities.fs"
#load "Functions.fs"

что дает мне error FS0039: The namespace or module 'Utilities' is not defined когда я пытаюсь отправить его в FSI с Alt-Enter,

Я пытался добавить то же пространство имен в верхней части файла скрипта, но это не нравится.

Что странно, так это то, что фоновый компилятор не кричит на меня.

Кажется, это работает, но это правильный подход?

#load "Utilities.fs"
open Company.Project.Namespace
#load "Functions.fs"

Есть ли где-нибудь "справочный" проект FSharp, который содержит примеры того, как интегрировать все эти вещи: пространства имен, модули, классы, файлы сценариев, тесты и т. Д.?

2 ответа

Решение

Я не эксперт FSI, но некоторые эксперименты показывают, что пространства имен поддерживаются только #load декларации (не через обычные взаимодействия - отправка группы объявлений пространства имен в VFSI через Alt-Enter не работает), и что разные взаимодействия вносят разные "экземпляры". Например, с файлом кода

namespace Foo

type Bar() =
    member this.Qux() = printfn "hi"

namespace Other

type Whatever() = class end

namespace Foo

module M =
    let bar = new Bar()
    bar.Qux()

Если я #load это не раз я получаю, например,

> [Loading C:\Program.fs]
hi

namespace FSI_0002.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0002.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0002.Foo
  val bar : Bar

> #load @"C:\Program.fs";;
> [Loading C:\Program.fs]
hi

namespace FSI_0003.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0003.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0003.Foo
  val bar : Bar

> new Foo.Bar();;
> val it : Foo.Bar = FSI_0003.Foo.Bar

Обратите внимание, что кажется, что FSI_0003.Foo.Bar скрывает версию FSI_0002.

Так что я думаю, что часть спецификации F#, которая говорит

Внутри группы объявлений пространства имен само пространство имен неявно открывается, если какие-либо предшествующие группы объявлений пространства имен или ссылочные сборки вносят вклад в это пространство имен, например

namespace MyCompany.MyLibrary 

   module Values1 = 
      let x = 1

namespace MyCompany.MyLibrary 

   // Implicit open of MyCompany.MyLibrary bringing Values1 into scope

   module Values2 = 
      let x = Values1.x

Однако это только открывает пространство имен, состоящее из предшествующих групп объявлений пространства имен.

Не взаимодействует с FSI, учитывая ограниченное понимание FSI пространств имен. В частности, я ожидаю, что в вашем примере откроется 'second #load', например: FSI_000N+1версия пространства имен, тогда как предыдущий код FSI_000N, Что может быть - объясняет, почему явное open взаимодействие исправляет это; вы приносите существующее, не затененное FSI_000N до верхнего уровня, прежде чем пытаться (неявно) ссылаться на него позже.

Я тоже относительно новичок в этом, но это то, что работает для меня, когда я тестирую в файле fsx:

#if INTERACTIVE
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsec.dll"
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsecCS.dll"
#endif

open FParsec.Primitives  
open FParsec.CharParsers

затем мой код, который использует эти библиотеки.

Другие вопросы по тегам