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

Я знаю другие questions о модулях и пространствах имен в 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.

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

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

Это похоже на работу, но верно ли это?

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

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

Ответ 1

Я не эксперт в 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 пространств имен. В частности, я ожидаю, что "вторая #load" из вашего примера откроется, например. FSI_000N+1 версии пространства имен, тогда как предыдущий код находился в FSI_000N. Возможно, это объясняет, почему явное взаимодействие open исправляет его; вы привносите существующие, незатененные элементы FSI_000N на верхний уровень, прежде чем пытаться (неявно) ссылаться на него позже.

Ответ 2

Я тоже относительно новичок, но это то, что работает для меня, когда я тестирую файл 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

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