F# Library structure - f#

I'm doing some restructuring of a project of mine, and decided to make a separate library project for a big part of it.
My problem lays in that I have multiple files with modules where many of them should be hidden from user API, how do I achieve this? I have not tried this before so are unfamiliar to how the library structure are different from commandline projects, and how to scope things correctly. If I can see every file in the lib project from
other project why do we have the Library.fs file?
To formalize a little. Say that I have SomeCode.fs and Library.fs
SomeCode.fs
module SomeCode
type SomeType = ...
let someFunc1 ... = ...
// things to hide here
// depend on hidden code
let SomeFunc2 ... = ...
Library.fs
namespace SomeLib
module Mod1 = ...
This is intended to target other F# project. How to structure this so the API would only see the right things, and still be maintainable?

internal is your friend here. If you declare a module
module internal MyNamSpace.MySecretModule
this is only accessible from within your project.
The module Library you keep public, and this is your API.
internal can also be used on individual functions, in case you want to hide just some functions.
A fairly common way of hiding part of a module is also to employ the following pattern
module MyModule =
[<AutoOpen>]
module internal MySecretModule =
let apa = 1
// Bunch of other internal stuff
// Can use stuff from MySecretModule, but other projects cannot
let bepa = apa + 1

Related

Is there a way to import (open) specific functions in F#?

Instead of importing a whole module, is there a way to open specific functions in another module? Something like:
open TestFuncs with [myTestFuncInOtherModule]
As you can see in the docs, the open keyword doesn't actually load a module or namespace. It just allows you to refer to elements in that module/namespace without refering to their fully qualified name.
Being so, when you use open you're just making it easier to call the functions in that module, not actually importing/loading them in memory, so the short answer for this question is that using the open keyword you can't do this to only one function.
You can achieve the same thing easily with a let binding, though:
let f = TestFuncs.myTestFuncInOtherModule
It's not currently possible, but I've actually put in a request for this to be added to the language. If you want to see this added in F# 4.0, one thing you could do is go vote for that request.
Another good workaround, that hasn't been mentioned yet by other answers, is to "pseudo-open" modules: assign a short name to modules whose contents you want to use. Like so:
module TP = Microsoft.FSharp.Data.TypeProviders
type mySchema = TP.SqlDataConnection<"...">
let db = mySchema.GetDataContext()
This gives you the convenience of not having to type the whole module name every time you want to reference its contents, but you maintain control of your namespace: this way there's no chance of accidental name collisions when you update a module to a new version and it adds new names.
You can refer to particular functions in another module using full function name ModuleName.funcName:
module One =
let square x = x * x
module Two =
let anothersquare x = One.square x

Should F# functions be placed in modules, classes, or another structure? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm starting to code in F# and am calling functions from functions with functions as parameters - there are plenty of learning resources online. Now I am trying to put together the pieces into something more than just a collection of functions. Unfortunately I'm not finding many resources dealing with structure, design, or even how the 'bits' tie together.
I've found the namespace keyword (e.g. namespace MyOnlyNamespace) but I get a compiler error on the functions that I've placed inside the namespace:
Namespaces cannot contain values. Consider using a module to hold your value declarations.
When I add module CoolFunctions I get
Unexpected start of structured construct in definition. Expected '=' or other token
So I have a multi-part question (but please answer any part that you can)
What is a module?
Is it like a class (something like a VB.NET module) or is it something else altogether?
If something else, then are there classes in F#?
Are there other structures that I should be using instead?
How do I declare a module?
To give some specific recommendations about choosing between namespaces, modules abd classes in F#:
If you're writing functions using let that are expected to be used from F#, then putting them inside a module is the best choice. This gives you API similar to List.map and other basic F# functions.
Regarding naming, you should use camelCase unless you expect C# users to call the functions too. In that case, you should use PascalCase (and note that module will be compiled to a static class).
If you're writing type delcarations, then these should generally be placed in a namespace. They are allowed inside modules too, but then they'll be compiled as nested classes.
If you're writing F# classes, then they should be placed in namespaces too. In generall, if you're writing F# code that will be called by C#, then using classes is the best mechanism as you get full control of what the user will see (F# class is compiled to just a class).
If you have a file, it can either start with namespace Foo.Bar or module Foo.Bar, which places all code in the file inside a namespace or a module. You can always nest more modules inside this top-level declaration. A common pattern is to start with a single namespace and then include some type and module declarations in the file:
namespace MyLibrary
type SomeType =
// ...
module SomeFuncs =
let operation (st:SomeType) = // ...
concerning the design of F# components there is a very good draft online.
JPalmer allready pointed you to the syntay problems but I think some other questions deserve more:
What is a module?
Yes JPalmer is right - modules are compiled into static classes but do we really care inside F#?
IMHO you should use more modules than classes when programming in F#.
In OOP you define your classes and the methods within.
In FP you define simple types (without behaviour) and a bunch of functions to transform them. And the natural place to collect those functions is the module.
Is it like a class (something like a VB.NET module) or is it
something else altogether?
A VB module is indeed a good comparision.
If something else, then are there classes in F#?
Yes you can use classes in F# - it's a complete .net languague and .net is OOP. You can do practically everything in F# you could do in C# of VB.net (only certain cases generic constraints can be a pain)
Are there other structures that I should be using instead?
No - collect your functions into modules but of course use records and abstract data-types for your data.
How do I declare a module?
Have a look at the online docs: Modules (F#) - there you will find everything you need.
What is a module:
A module is compiled down to a static class. But I think of modules as being analogous to namespaces in C#
there are classes in F# - use
type SomeType(constructor,args) =
....
If you have
namespace Name
module Mod
....
this won't compile - as you know, you can use a few alternatives
module Namespace.Module
as the first line in the file
or
namespace Name
module Mod =
....

F# mutual recursion between modules

For recursion in F#, existing documentation is clear about how to do it in the special case where it's just one function calling itself, or a group of physically adjacent functions calling each other.
But in the general case where a group of functions in different modules need to call each other, how do you do it?
I don't think there is a way to achieve this in F#. It is usually possible to structure the application in a way that doesn't require this, so perhaps if you described your scenario, you may get some useful comments.
Anyway, there are various ways to workaround the issue - you can declare a record or an interface to hold the functions that you need to export from the module. Interfaces allow you to export polymorphic functions too, so they are probably a better choice:
// Before the declaration of modules
type Module1Funcs =
abstract Foo : int -> int
type Module2Funcs =
abstract Bar : int -> int
The modules can then export a value that implements one of the interfaces and functions that require the other module can take it as an argument (or you can store it in a mutable value).
module Module1 =
// Import functions from Module2 (needs to be initialized before using!)
let mutable module2 = Unchecked.defaultof<Module2Funcs>
// Sample function that references Module2
let foo a = module2.Bar(a)
// Export functions of the module
let impl =
{ new Module1Funcs with
member x.Foo(a) = foo a }
// Somewhere in the main function
Module1.module2 <- Module2.impl
Module2.module1 <- Module1.impl
The initializationcould be also done automatically using Reflection, but that's a bit ugly, however if you really need it frequently, I could imagine developing some reusable library for this.
In many cases, this feels a bit ugly and restructuring the application to avoid recursive references is a better approach (in fact, I find recursive references between classes in object-oriented programming often quite confusing). However, if you really need something like this, then exporting functions using interfaces/records is probably the only option.
This is not supported. One evidence is that, in visual stuido, you need to order the project files correctly for F#.
It would be really rare to recursively call two functions in two different modules.
If this case does happen, you'd better factor the common part of the two functions out.
I don't think that there's any way for functions in different modules to directly refer to functions in other modules. Is there a reason that functions whose behavior is so tightly intertwined need to be in separate modules?
If you need to keep them separated, one possible workaround is to make your functions higher order so that they take a parameter representing the recursive call, so that you can manually "tie the knot" later.
If you were talking about C#, and methods in two different assemblies needed to mutually recursively call each other, I'd pull out the type signatures they both needed to know into a third, shared, assembly. I don't know however how well those concepts map to F#.
Definetely solution here would use module signatures. A signature file contains information about the public signatures of a set of F# program elements, such as types, namespaces, and modules.
For each F# code file, you can have a signature file, which is a file that has the same name as the code file but with the extension .fsi instead of .fs.

Signature Files and Access Modifers in F#

I've recently been trying to learn the Object-Oriented aspects of F#, and have become curious about how to restrict access to types/modules in the language.
More specifically, I want to know the difference between writing this:
Example.fsi
module Stack =
val foo : string
Example.fs
module Stack =
let foo = "foo"
let bar = "bar"
and alternatively this:
module Stack =
let foo = "foo"
let private bar = "bar"
Do they not accomplish exactly the same thing in the end? Coming from a C# background, I'm much inclined just to use the access modifiers over signature (FSI) files. They seem to be more versatile (can apply to modules/types in namespaces, for example), whereas I don't any situation in which signature files offer something that access modifiers don't.
They accomplish almost the same thing. (Note that you can use an .fsi file for types in namespaces too, was unsure what your comment about that meant.)
A signature file has a couple advantages:
You can make entities public for the duration of the file, but then private to the subsequent files of the project.
You can have just your short summary in the signature file, so the public interface is easy to read without having to scan tons of code.
The first bullet is not to be trifled with - within-assembly encapsulation like this is actually a pretty huge feature for very large projects. Being able to define a few types which are public to one another within File1.fs, but then only have a subset of those types/methods be public to the rest (File2.fs, File3.fs, etc.) is quite useful (a little bit like 'friend' in C++).

F# and namespace

I have an application, call it App1. It is mostly C#. I'm writing a dll in F#. It cointains a class, Class1. I want this class to belong to the App1 namespace.
If I add namespace App1 on the top of my .fs file, it complains that a namespace cannot contain values (I have some lets in my file).
If I add "module App1" under the namespace, it compiles, but I cannot access the namespace from outside. Any help?
Thanks
It's simplest to separate out the class code from the freestanding functions -- I'd do something like
#light
namespace App1
open ModuleWithFunctionsIn
type Class1 = class
(* stuff goes here *)
end
and pull the free-standing functions in from a separate module
I do not remember exact answer, but what I did is inspecting F# assemblies with .NET Reflector. Often this answers all questions like this.

Resources