CATEGORII DOCUMENTE |
Asp | Autocad | C | Dot net | Excel | Fox pro | Html | Java |
Linux | Mathcad | Photoshop | Php | Sql | Visual studio | Windows | Xml |
Namespaces, Modules and Signatures
F# uses three primary concepts to organize software constructs hierarchically: namespaces, modules and type definitions. In this section we'll take a look at namespaces and modules. Namespaces, modules and types can all act as containers for values and members. The following table shows the different kinds of containers you will meet as you explore F# and .NET libraries (for completeness we've included type abbreviations, which may not act as container for other constructs within the hierarchical structure of your software):
Namespaces, Modules and Type Definitions as Containers
Entity Description
Namespace A container for namespaces, modules, types and private values[DS1] . Multiple DLLs can contribute to the same namespace. Examples: System, Microsoft.FSharp
Module A container for nested type definitions, type abbreviations, modules and values. Only one DLL may define a particular module. Examples: Microsoft.FSharp.Collections.Map, Microsoft.FSharp.Collections.List
Concrete Type Definition A container for members and further type definitions[DS2] , as well as defining a type constructor in the type system. Only one DLL may define a particular concrete type. Examples: System.String, System.Int32
Type Abbreviation A type equation such as type int = System.Int32. May not act as a container for additional members, values or types. The abbreviated path may be used to reference the members contained by a concrete type. Examples: string (for System.String), int (for System.Int32)
Namespaces may contain module and type definitions. We discuss module and type definitions below, though give some simple examples here. Namespaces may also contain private value definitions, discussed at the end of this chapter. Here is a simple example of a module containing two type definitions:
namespace Acme.Widgets
type Widget =
type Wheel = Square | Round | Triangle
Note that a single namespace can include multiple type definitions. Namespaces are open in the sense that multiple source files and assemblies may contribute to the same namespace. For example, another implementation file or assembly could contain the following definitions:
namespace Acme.Widgets
type Lever = PlasticLever | WoodenLever
namespace Acme.Suppliers
type LeverSupplier =
This file contributes to two namespaces: Acme.Widgets and Acme.Suppliers. Indentation is required if a single file contributes to multiple namespaces and the #light syntax option is being used.
Modules are simple containers used to contain values, type definitions and additional sub-modules. A set of declarations without a module declaration is implicitly placed in a module derived from the name of the implementation file. This name is determined by capitalizing the first name of the file. For example, if a file widgetWheels.fs contains
File widgetWheels.fs
open Acme.Widgets
let wheelCornerCount = Map.of_list [(Wheel.Square, 4);
(Wheel.Triangle, 3);
(Wheel.Round, 0) ] ]
then the value is placed in a module WidgetWheels (derived from the file name) and the value in the module can be accessed via the long path WidgetWheels.wheelsTable.
Modules can also be named explicitly. For example, we could have defined the above module as follows (regardless of the name of the file containing the constructs):
File myfile.fs
module Acme.Widgets.WidgetWheels
let wheelCornerCount = Map.of_list [(Wheel.Square, 4);
(Wheel.Triangle, 3);
(Wheel.Round, 0) ] ]
Here the first line gives the name for the module defined by the file. The namespace is Acme.Widgets and the module name is WidgetWheels, and the full path to the value is Acme.Widgets.WidgetWheels. wheelCornerCount.
Modules may contain sub-modules, e.g.:
module Mynamespace.MyModule
module SubModule1 =
let v1 = 3 + 5
let v2 = 3 + 4
module SubModule2 =
let v1 = 1 + 2
let v2 = 1 + 3
Sub-modules may be optionally delimited by begin/end or / pairs :
module SubModule3 = begin
let v1 = 3 + 5
let v2 = 3 + 4
end
Implementation files may be given "types" via signature files, which can also be used to hide implementation constructs from the outside world. Signature files are typically named the same as the implementation file, though with the extension .fsi. For example, if we return to the first example from Chapter 2 and place the code in a file count.fs, in then the module can be given the following signature in a file count.fsi:
File count.fsi
val wordCount : string -> int * int
val showWordCount : string -> unit
File count.fs:
let wordCount text =
let words = String.split [' '] text
let wordSet = Set.of_list words
let nWords = words.Length
let nDups = words.Length - wordSet.Size
(nWords,nDups)
let showWordCount text =
let nWords,nDups = wordCount text
printf '--> %d words in the textn' nWords
printf '--> %d duplicate wordsn' nDups
Note that the syntax used for constructs in a signature file are identical to the inferred types reported by F# Interactive for the functions. The inferred types can also be reported by the F# command line compiler fsc.exe, using the -i option:
> fsc -i count.fs
(* module Count *)
val wordCount : string -> int * int
val showWordCount : string -> unit
Signature files can also be used to specify the types, modules and members present in an implementation file.
// Longer example needed here, e.g. from the F# library
[DS1]This is NYI as of 1.1.13
[DS2]Nested type definitions are NYI as of F# 1.1.13
[DS3]As of F# 1.1.13 a begin/end pair is always needed
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 712
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved