F# Math (III.) - Defining custom numeric types
In this article, we define an F# numeric type for calculating in the modular arithmetic (also called clock arithmetic) [1]. Modular arithmetic is used for calculations where we want to keep a value within a specified range by counting in cycles. For example, a maximal value on clock is 12 hours. When we add 11 hours and 3 hours, the value overflows and the result is 2 hours. Aside from clocks, this numeric system is also essential in cryptography or, for example, in music.
This tutorial shows several techniques that are essential when defining any new numeric type in F#. Most importantly, you’ll learn how to:
- Define a numeric type with overloaded operators
- Define a numeric literal for constructing numbers of our new type
- Enable calculating with our type in F# lists and matrices
- Hide implementation details of a numeric type
We define type IntegerZ5
that implements modular arithmetic with modulus 5, meaning that valid values are in the range
from 0 to 4 and we equip the type with operations such as addition and multiplication. When an operation produces a value that would
be outside of the range, we adjust it by adding or subtracting the modulus (in our case 5). Here are some examples of calculations
that we’ll be able to write:
2 + 1 = 3 (mod 5) 4 * 2 = 3 (mod 5) List.sum [ 0; 1; 2; 3 ] = 1 (mod 5)
In the first case, we can perform the operation without any adjustments. In the second case, we multiply 4 by 2 and get 8 as the
result, which is out of the required range. To correct it, we calculate the remainder after a division by 5 (written as 8 % 5
in F#),
which gives us 3. Finally, the last example shows that we’d also like to be able to use our type with lists. If we add values 0, 1, 2
and 3, we get 6 which is adjusted to 1.
This article is a part of a series that covers some F# and F# PowerPack features for numerical computing. Other articles in this series discuss matrices, defining custom numeric types and writing generic code. For links to other parts, see F# Math - Overview of F# PowerPack.
Defining the IntegerZ5 type
We’ll create an F# library containing our numeric type, so that it can be easily used from multiple applications. The approach we’ll use will follow the usual F# best practices for designing this kind of libraries, so you should follow similar steps when creating any other numeric type.
To start, we create a new F# Library project in Visual Studio. Once the project is created, remove the existing files
and add a new file named IntegerZ5.fs
. This file will contain the implementation of our type. We start by adding a
type IntegerZ5
into a namespace FSharp.Numeric
:
1: namespace FSharp.Numerics 2: 3: type IntegerZ5 = 4: | Z5 of int 5: member z.ToInt32() = 6: let (Z5 n) = z in n 7: override z.ToString() = 8: sprintf "%d (mod 5)" (z.ToInt32()) 9: 10: static member Create(n) = 11: let z5 = n % 5 12: Z5(max ((z5 + 5) % 5) z5)
The type is implemented as a discriminated union with a single case labeled Z5
. The case carries a value of type int
, but
the operations that we’ll provide for creating and calculating with IntegerZ5
will guarantee that the actual value will be
within the required range (0 to 4, inclusively). The fact that we use single-case discriminated union is merely an implementation
detail that allows us to implement operations with the type in a convenient way, but we'll later see how to hide this implementation detail.
The first two members convert an IntegerZ5
value to other types. To get an integer, we simply return the underlying value. When
formatting the value as a string, we append the "(mod 5)" string after the number, which is the usual way of denoting that the number
is in the modular arithmetic.
The last static members provide ways for constructing IntegerZ5
values. It takes an arbitrary integer as an argument and
adjusts it, so that it is within the specified range. This is done by calculating the remainder of a division by 5 and adding 5 in case
the result is negative (for example, -13 % 5
produces -3, and the result of max -3 2
will give us 2).
So far, we created a simple type that can be created and printed, but that’s all we can do with it so far. In the next section, we’ll equip our type with basic operators for calculating with it. As we’ll see, that’s all we need to use the type with some standard F# library functions.
Creating and calculating with IntegerZ5
Next, let's take the IntegerZ5
type and add operators for multiplying, adding and subtracting values of this type.
We’ll also add two members that provide easy access to frequently used constants 0 and 1 and we’ll provide a simple function for
constructing values of this type. The following listing adds several static members to the type:
1: type IntegerZ5 = 2: (Omitted) 3: static member (+) (Z5 a, Z5 b) = IntegerZ5.Create(a + b) 4: static member (-) (Z5 a, Z5 b) = IntegerZ5.Create(a - b) 5: static member (*) (Z5 a, Z5 b) = IntegerZ5.Create(a * b) 6: static member Zero = Z5 0 7: static member One = Z5 1
The three overloaded operators are implemented as static members with a special name. They take two parameters of type
IntegerZ5
and we use pattern matching (using the discriminated union case label Z5
) to immediately
extract the actual integer used to represent the number. After performing the numerical operation on integers, the result may be
out of the specified range, so we construct the result using the Create
member, which adjusts the integer. The Zero
and One
members simply construct value using the Z5
union case, because 0 and 1 are always valid
values (so there is no need for calling the Create
member).
Most of the standard F# numeric types can be created from other numeric types by calling a conversion function of the same
name as the name of the type. For example float 42
returns a floating point number 42.0 and byte 42.0
converts a
floating point number to a byte value 42uy
.
Numeric type conversion functions are written in a way so that they work with any numeric type that supports the
conversion in some way. This means that we can write byte 42
as well as byte 42.0
, but not for example
byte (new System.Random())
. This behavior is achieved using static member constraints, which allow the function to
specify that the argument needs to be of any type that provides a specific method.
To write a conversion function for IntegerZ5
type, we could either use static member constraints explicitly, or
we can use some existing function (such as int
) and let the F# type inference deduce the constraints automatically.
The following listing uses the second approach:
1: [<AutoOpen>] 2: module IntegerZ5TopLevelOperations = 3: let inline z5 a = IntegerZ5.Create(int a)
The function z5
needs to be marked as inline
, which allows us to use static member constraints. Inside
the body, we first convert the argument to an integer using the int function and then construct IntegerZ5
from the returned
integer. The static member constraints are propagated automatically and we’ll look at them in more details later.
Since functions cannot be declared inside a namespace, we need to enclose our function in a module. We want to make it available automatically
whenever the user of our library opens the FSharp.Numerics
namespace, which can be done by adding the AutoOpen
attribute to the module declaration.
Testing numeric type interactively
As a next step, we’ll use F# interactive to verify that the code we wrote so far works as expected. At this point, we didn't even build the library. We just wrote some F# source code and want to test the source code without building the library. We'll use interactive tests written in an F# script file. Once you build the library, it is quite easy to turn those into proper unit tests using NUnit, xUnit or other testing frameworks.
To test the type we implemented at the source code level, we first add a new F# Script File (Add -> New Item... -> F# Script File)
named Tests.fsx
. In this file, we load the content of IntegerZ5.fs
and register a printer to specify how the
F# Interactive tool should output values of our type:
1: #load "IntegerZ5.fs" 2: open FSharp.Numerics 3: 4: fsi.AddPrinter(fun (z:IntegerZ5) -> z.ToString())
The first command loads an F# source code and evaluates it in the F# Interactive tool. Next, we open the namespace FSharp.Numerics
,
which contains our type. Finally, we call the AddPrinter
member of the global fsi
value. The parameter is a
lambda function that takes value of our IntegerZ5
type and returns a string by simply calling the ToString
member we
provided. Note that we need to add the type annotation, because AddPrinter
is a generic member. The type annotation
allows it to determine a type for which we’re specifying the printer.
Now, we can test our function for creating IntegerZ5
values and operators for working with them:
1: let a = z5 3.0 2: let b = z5 7 3: val a : IntegerZ5 = "3 (mod 5)" 4: val b : IntegerZ5 = "2 (mod 5)" 5: 6: a * b; 7: val it : IntegerZ5 = "1 (mod 5)" 8: a + b 9: val it : IntegerZ5 = "0 (mod 5)"
As we can see, when the F# Interactive outputs a value of our type, it uses the printer we specified. The output such as
“3 (mod 5)” makes it clear that the value is calculated in modulus arithmetic of base 5. The first two let
bindings show
that the z5
function works with any numeric types (including floating point numbers and integers) and that it
automatically calculates the modulus of the number. The last two examples show that overloaded operators we provided also
follow the rules of modulus arithmetic.
So far, we’ve been using the operators directly. The way we wrote the IntegerZ5
type also allows us to use it
with some functions from the F# core libraries. For example, if we create a list of IntegerZ5
values, we can sum
the list using the overloaded operators we provided simply like this:
1: List.sum [ z5 0; z5 1; z5 2; z5 3; z5 4 ] 2: val it : IntegerZ5 = "0 (mod 5)"
How does the List.sum
function know that it needs to use the overloaded operator of IntegerZ5
type?
The function is implemented using static member constraints and requires that the type of the elements provides a + operator and
also a Zero
member. The compiler knows that our type provides the required members, so it allows us to use List.sum
for our type.
We'll look at implementing functions like this in the next article of the series.
When creating values of IntegerZ5
in this step, we used the z5
conversion function. Alternatively, we
could use the IntegerZ5.Create
member, but that leads to a more heavyweight notation. In the next step, we’ll
see how to use numeric literals to make the syntax more convenient.
Providing numeric literals for IntegerZ5
Values of built-in numeric types such as int64
, byte
or float32
can be created using
special numeric literals -30L
, 127uy
and 42.0f
. The F# makes it possible to provide
a similar literal for our own numeric types. There are several limitations to what kind of literals we can define. Briefly,
the literal must end with one of characters that are reserved for this purpose by the F# language. Additionally, the literal
must consist only of numeric symbols (so for example 12#3Z
isn’t allowed).
To define a literal, we need to write a module with a special name. Inside the module, we implement several functions that are used automatically in the F# compiler whenever a literal is used:
1: module NumericLiteralZ = 2: let FromZero () = Z5 0 3: let FromOne () = Z5 1 4: let FromInt32 a = IntegerZ5.Create(a%5) 5: let FromInt64 a = IntegerZ5.Create(int(a%5L))
The name of the module consists of the special name NumericLiteral
followed by a symbol Z
which we’ll use for writing
our literals. This means that we’ll be able to write literals such as 0Z
, 1Z
and 42Z
. The module may provide
several functions to enable several sizes of literals.
If we included only the first two functions (FromZero
and FromOne
) we would be able to write only 0Z
and 1Z
.
The next two functions enable writing literals for other numbers that fit into integer values. To support numeric literals that are larger than int64
,
we could also provide the FromString
method. Note that this wouldn’t allow writing literals consisting of non-numeric characters. The main use
of this method is to enable arbitrarily sized integer values, so we don’t provide it in the above example.
The following listing shows a few examples of using our newly defined numeric literals:
1: 6Z 2: val it : IntegerZ5 = "1 (mod 5)" 3: 3Z * (4Z + 2Z) 4: val it : IntegerZ5 = "3 (mod 5)"
As we can see, numeric literals make working with custom numeric data types easier. Since our numeric type is almost finished now, we’ll look at compiling it into a redistributable library in the next step.
Adding F# Signature file
Signature files can be added to a project to specify which of the members and values from an implementation file
(such as IntegerZ5.fs
) should be publicly exported by the compiled library. A signature file lists members
and functions together with their type signatures, which also makes it a useful source of information about our library.
The name of the file should be the same as the name of the implementation file, but it should have the fsi extension. In our case,
we’ll add a file named IntegerZ5.fsi
. The file needs to be passed to the compiler before the implementation file.
In Visual Studio, this means that you need to move the file before the implementation file in the Solution Explorer. This can be
done by right-clicking on the file and selecting the “Move Up” command.
The listing below shows the source code of the signature file. Most of the type signatures that you can see in the listing can be inferred automatically by the F# compiler. An easy way of extracting the first version of F# signature file from the source code is selecting the entire content of the implementation file and evaluating it interactively. The F# Interactive prints all the inferred type signatures and we can easily copy them to the signature file.
Nevertheless, we’ll need to make one notable addition to the generated type signature. The listing also shows the type signature
of the z5
function, which is quite interesting:
1: namespace FSharp.Numerics 2: 3: [<Sealed>] 4: type IntegerZ5 = 5: member ToInt32 : unit -> int 6: override ToString : unit -> string 7: static member Create : int -> IntegerZ5 8: static member One : IntegerZ5 9: static member Zero : IntegerZ5 10: static member ( + ) : IntegerZ5 * IntegerZ5 -> IntegerZ5 11: static member ( * ) : IntegerZ5 * IntegerZ5 -> IntegerZ5 12: static member ( - ) : IntegerZ5 * IntegerZ5 -> IntegerZ5 13: 14: module NumericLiteralZ = 15: val FromZero : unit -> IntegerZ5 16: val FromOne : unit -> IntegerZ5 17: val FromInt32 : int -> IntegerZ5 18: val FromInt64 : int64 -> IntegerZ5 19: 20: module IntegerZ5TopLevelOperations = 21: val inline z5 : ^a -> IntegerZ5 when 22: ^a : (static member op_Explicit : ^a -> int)
The signature file starts with a namespace declaration, which is the same as the declaration in the implementation file. Next, it
contains a single type signature and two module signatures. Note that the IntegerZ5
type is marked with the Sealed
attribute. This is required, because the signature file needs to reveal what kind of file we are declaring. For F# types such as records
and discriminated unions, we use Sealed
meaning that the type is not extensible.
Type signatures of the members of our numeric type as well as functions in the NumericLiteralZ
module are mostly straightforward.
The function z5
in the last module is far more interesting. As noted earlier, the function is implemented so that it works on
any argument that can be converted into an integer. In practice, this means that the type of the argument needs to provide a static member named
op_Explicit
taking the type of the argument and returning integer.
Determining whether a type of the argument has a certain method cannot be expressed in .NET generics, so we use F# specific feature named
static member constraints. This works only for so-called hat types (such as ^a
). Hat types are inlined during the compilation,
so the function also needs to be marked as inline
.
Finally, it is also worth noting that if we added op_Explicit
member to our IntegerZ5
type, it would be possible to
use our type as parameter of the int
function (so we could write for example int 3Z
).
Supporting matrices using global associations
Our numeric type can be used with some standard library functions such as List.sum
, because they implement certain members that are
required by static member constraints of List.sum
. However, this approach doesn't work with complex data types such as generic matrices.
If we try to write any matrix computation with our type, it will not work, because generic Matrix type isn’t automatically able to use
the overloaded operators and members we provided.
In order to support matrices we need to provide a so-called numeric association. This is a simple interface containing numeric operations that can be performed on our type. The interface needs to be registered in a global table maintained by the F# PowerPack library, so that any F# code can get the interface from the table and use it for performing operations with our type.
The F# PowerPack library contains a hierarchy of interfaces that represent various sets of numeric operations that we may be able to
provide. We’ll implement the most basic interface called INumeric<'T>
and represent a simple numeric type. Other
interfaces available are for example IIntegral<'T>
, which provides operations such as DivRem
(division with a remainder)
or IFloating<'T>
, which additionally includes floating point operations such as Sqrt
.
The simplest way to implement the interface is to use object expressions and create a singleton value implementing it. We also need to provide
an operation that registers the instance in the GlobalAssociations
table:
1: module IntegerZ5Associations = 2: let IntegerZ5Numerics = 3: { new INumeric<IntegerZ5> with 4: member z.Zero = IntegerZ5.Zero 5: member z.One = IntegerZ5.One 6: member z.Add(a,b) = a + b 7: member z.Subtract(a,b) = a - b 8: member z.Multiply(a,b) = a * b 9: member z.Equals(Z5 a, Z5 b) = (a = b) 10: member z.Compare(Z5 a, Z5 b) = compare a b 11: member z.Negate(a) = 0Z - a 12: member z.Abs(a) = a 13: member z.Sign(Z5 a) = Math.Sign(a) 14: member z.ToString(Z5 n,fmt,fmtprovider) = 15: n.ToString(fmt,fmtprovider) + " (mod 5)" 16: member z.Parse(s,numstyle,fmtprovider) = 17: z5 (System.Int32.Parse(s,numstyle,fmtprovider)) } 18: 19: let Init() = 20: GlobalAssociations.RegisterNumericAssociation IntegerZ5Numerics
Most of the operations can be implemented directly in terms of operators that we already provided in the IntegerZ5
type, so the purpose of the
INumeric<'T>
interface is simply to make these operations accessible indirectly. Some other operations such as Compare
,
Sign
or ToString
can be implemented using the underlying integer (which we can extract by writing the pattern
Z5
a in place of parameter).
The module also provides Init
function, which registers our instance in the GlobalAssociations
table. Ideally,
the registration would be done automatically when the IntegerZ5
type is used for the first time, but this is unfortunately
not easy to achieve. Instead, we'll write a function that needs to be called explicitly (to make this automatic, you could move the code
to a static constructor of the IntegerZ5
type).
To make the module visible in the compiled library, we also need to include its type signature in the F# Signature file that we added earlier. This can be done by adding the code from the following listing:
1: module IntegerZ5Associations = 2: val IntegerZ5Numerics : INumeric<IntegerZ5> 3: val Init : unit -> unit
Now that our library is complete, we can compile and use the created assembly in other F# projects. In this tutorial, we didn’t aim to create a C# compatible type, however, the type would be also usable from C# (most importantly, all the overloaded operators and members of the type would work in C#).
As a final step, we’ll look how to load the compiled library in F# interactive and use our type to do a simple computation
using generic Matrix
type:
1: #r "FSharp.PowerPack.dll" 2: #r "bin\Debug\FSharp.Numerics.dll" 3: 4: open FSharp.Numerics 5: module MatrixG = Matrix.Generic 6: 7: IntegerZ5Associations.Init() 8: 9: let ys = MatrixG.init 5 5 (fun a b -> (z5 a)) 10: let xs = MatrixG.init 5 5 (fun a b -> (z5 b)) 11: val ys : Matrix<IntegerZ5> = (...) 12: val xs : Matrix<IntegerZ5> = (...) 13: 14: xs .* ys 15: val it : Matrix<IntegerZ5> = 16: matrix [[0 (mod 5); 0 (mod 5); 0 (mod 5); 0 (mod 5); 0 (mod 5)] 17: [0 (mod 5); 1 (mod 5); 2 (mod 5); 3 (mod 5); 4 (mod 5)] 18: [0 (mod 5); 2 (mod 5); 4 (mod 5); 1 (mod 5); 3 (mod 5)] 19: [0 (mod 5); 3 (mod 5); 1 (mod 5); 4 (mod 5); 2 (mod 5)] 20: [0 (mod 5); 4 (mod 5); 3 (mod 5); 2 (mod 5); 1 (mod 5)]]
After referencing F# PowerPack and our library, we open the namespace FSharp.Numerics
, which contains our type and define a
module alias MatrixG
to simplify access to generic Matrix
type. Next we call the Init
function
to register the global numeric associations for our type.
Finally, we construct two matrices of the size 5x5
– the first one contains increasing values of the IntegerZ5
type along
the first dimension and the values in the second matrix increase along the second dimension. We use point-wise multiplication of these two
matrices to produce a simple table that shows results of multiplying all possible combinations of IntegerZ5
values.
Summary
In this article, we looked at implementing a custom numeric type. Although you probably won't need to implement a custom
numeric type very often, it may be useful. Aside from modular arithmetic, you may want to implement a type that represents
quadruples of values (to represent colors) or a type to represent 3D vectors. The F# PowerPack library uses the techniques
described in this article to implement BigRational
and complex
types that I introduced in
an earlier article.
When implementing a numeric type, there is quite a few features that you may want to support. In this article, we
defined overloaded operators and members that are required by static member constraints, so that we could use
functions like List.sum
. Then we also defined numeric literals to be able to write 1Z
instead of z5 1
. Finally, we implemented the INumeric<'T>
interface, which makes
it possible to use our type with generic matrices from F# PowerPack, which I covered in the
previous article of the series.
References & Links
- [1] Modular arithmetic - Wikipedia.org
- [2] F# PowerPack (source code and binary packages) - CodePlex
- [3] Numeric Computing - Real World Functional Programming on MSDN
- [4] Numerical Libraries for F# and .NET - Real World Functional Programming on MSDN
| Z5 of int
with
member ToInt32 : unit -> int
override ToString : unit -> string
static member Create : n:int -> IntegerZ5
end
Full name: FSharp.Numerics.Version1.IntegerZ5
type: IntegerZ5
implements: System.IEquatable<IntegerZ5>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<IntegerZ5>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
val int : 'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
type: int<'Measure>
implements: System.IComparable
implements: System.IConvertible
implements: System.IFormattable
implements: System.IComparable<int<'Measure>>
implements: System.IEquatable<int<'Measure>>
inherits: System.ValueType
type: IntegerZ5
implements: System.IEquatable<IntegerZ5>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<IntegerZ5>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
Full name: FSharp.Numerics.Version1.IntegerZ5.ToInt32
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
Full name: FSharp.Numerics.Version1.IntegerZ5.ToString
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Full name: FSharp.Numerics.Version1.IntegerZ5.Create
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
Full name: Microsoft.FSharp.Core.Operators.max
| Z5 of int
with
member ToInt32 : unit -> int
override ToString : unit -> string
static member Create : n:int -> IntegerZ5
static member One : IntegerZ5
static member Zero : IntegerZ5
static member ( + ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( * ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( - ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
end
Full name: FSharp.Numerics.IntegerZ5
type: IntegerZ5
implements: System.IEquatable<IntegerZ5>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<IntegerZ5>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
member z.ToInt32() =
let (Z5 n) = z in n
override z.ToString() =
sprintf "%d (mod 5)" (z.ToInt32())
static member Create(n) =
let z5 = n % 5
Z5(max ((z5 + 5) % 5) z5)
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
Full name: FSharp.Numerics.IntegerZ5.Zero
Full name: FSharp.Numerics.IntegerZ5.One
type AutoOpenAttribute =
class
inherit System.Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
end
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
type: AutoOpenAttribute
implements: System.Runtime.InteropServices._Attribute
inherits: System.Attribute
--------------------
new : unit -> AutoOpenAttribute
--------------------
new : path:string -> AutoOpenAttribute
from FSharp.Numerics
Full name: FSharp.Numerics.IntegerZ5TopLevelOperations.z5
Full name: Microsoft.FSharp.Compiler.Interactive.Settings.fsi
Full name: Script.Testing.a
type: IntegerZ5
implements: System.IEquatable<IntegerZ5>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<IntegerZ5>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
Full name: Script.Testing.b
type: IntegerZ5
implements: System.IEquatable<IntegerZ5>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<IntegerZ5>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of 'T * 'T list
with
interface System.Collections.IEnumerable
interface System.Collections.Generic.IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
end
Full name: Microsoft.FSharp.Collections.List<_>
type: List<'T>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<List<'T>>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
implements: System.Collections.Generic.IEnumerable<'T>
implements: System.Collections.IEnumerable
Full name: Microsoft.FSharp.Collections.List.sum
Full name: Script.Testing.NumericLiteralZ.FromZero
Full name: Script.Testing.NumericLiteralZ.FromOne
Full name: Script.Testing.NumericLiteralZ.FromInt32
Full name: Script.Testing.NumericLiteralZ.FromInt64
type: int64
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int64>
implements: System.IEquatable<int64>
inherits: System.ValueType
Full name: Script.IntegerZ5Associations.IntegerZ5Numerics
type INumeric<'T> =
interface
abstract member Abs : 'T -> 'T
abstract member Add : 'T * 'T -> 'T
abstract member Compare : 'T * 'T -> int
abstract member Equals : 'T * 'T -> bool
abstract member Multiply : 'T * 'T -> 'T
abstract member Negate : 'T -> 'T
abstract member Parse : string * Globalization.NumberStyles * IFormatProvider -> 'T
abstract member Sign : 'T -> int
abstract member Subtract : 'T * 'T -> 'T
abstract member ToString : 'T * string * IFormatProvider -> string
abstract member One : 'T
abstract member Zero : 'T
end
Full name: Microsoft.FSharp.Math.INumeric<_>
--------------------
INumeric
| Z5 of int
with
member ToInt32 : unit -> int
override ToString : unit -> string
static member Create : n:int -> IntegerZ5
static member One : IntegerZ5
static member Zero : IntegerZ5
static member ( + ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( * ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( - ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
end
Full name: FSharp.Numerics.IntegerZ5
type: IntegerZ5
implements: IEquatable<IntegerZ5>
implements: Collections.IStructuralEquatable
implements: IComparable<IntegerZ5>
implements: IComparable
implements: Collections.IStructuralComparable
type: IntegerZ5
implements: IEquatable<IntegerZ5>
implements: Collections.IStructuralEquatable
implements: IComparable<IntegerZ5>
implements: IComparable
implements: Collections.IStructuralComparable
type: IntegerZ5
implements: IEquatable<IntegerZ5>
implements: Collections.IStructuralEquatable
implements: IComparable<IntegerZ5>
implements: IComparable
implements: Collections.IStructuralComparable
Object.Equals(obj: obj) : bool
abstract member INumeric.Equals : 'T * 'T -> bool
type: int
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
type: int
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
Full name: Microsoft.FSharp.Core.Operators.compare
class
static val PI : float
static val E : float
static member Abs : System.SByte -> System.SByte
static member Abs : int16 -> int16
static member Abs : int -> int
static member Abs : int64 -> int64
static member Abs : float32 -> float32
static member Abs : float -> float
static member Abs : decimal -> decimal
static member Acos : float -> float
static member Asin : float -> float
static member Atan : float -> float
static member Atan2 : float * float -> float
static member BigMul : int * int -> int64
static member Ceiling : decimal -> decimal
static member Ceiling : float -> float
static member Cos : float -> float
static member Cosh : float -> float
static member DivRem : int * int * int -> int
static member DivRem : int64 * int64 * int64 -> int64
static member Exp : float -> float
static member Floor : decimal -> decimal
static member Floor : float -> float
static member IEEERemainder : float * float -> float
static member Log : float -> float
static member Log : float * float -> float
static member Log10 : float -> float
static member Max : System.SByte * System.SByte -> System.SByte
static member Max : System.Byte * System.Byte -> System.Byte
static member Max : int16 * int16 -> int16
static member Max : uint16 * uint16 -> uint16
static member Max : int * int -> int
static member Max : uint32 * uint32 -> uint32
static member Max : int64 * int64 -> int64
static member Max : uint64 * uint64 -> uint64
static member Max : float32 * float32 -> float32
static member Max : float * float -> float
static member Max : decimal * decimal -> decimal
static member Min : System.SByte * System.SByte -> System.SByte
static member Min : System.Byte * System.Byte -> System.Byte
static member Min : int16 * int16 -> int16
static member Min : uint16 * uint16 -> uint16
static member Min : int * int -> int
static member Min : uint32 * uint32 -> uint32
static member Min : int64 * int64 -> int64
static member Min : uint64 * uint64 -> uint64
static member Min : float32 * float32 -> float32
static member Min : float * float -> float
static member Min : decimal * decimal -> decimal
static member Pow : float * float -> float
static member Round : float -> float
static member Round : decimal -> decimal
static member Round : float * int -> float
static member Round : float * System.MidpointRounding -> float
static member Round : decimal * int -> decimal
static member Round : decimal * System.MidpointRounding -> decimal
static member Round : float * int * System.MidpointRounding -> float
static member Round : decimal * int * System.MidpointRounding -> decimal
static member Sign : System.SByte -> int
static member Sign : int16 -> int
static member Sign : int -> int
static member Sign : int64 -> int
static member Sign : float32 -> int
static member Sign : float -> int
static member Sign : decimal -> int
static member Sin : float -> float
static member Sinh : float -> float
static member Sqrt : float -> float
static member Tan : float -> float
static member Tanh : float -> float
static member Truncate : decimal -> decimal
static member Truncate : float -> float
end
Full name: System.Math
Math.Sign(value: decimal) : int
Math.Sign(value: float) : int
Math.Sign(value: float32) : int
Math.Sign(value: int64) : int
Math.Sign(value: int) : int
Math.Sign(value: int16) : int
Math.Sign(value: sbyte) : int
Object.ToString() : string
abstract member INumeric.ToString : 'T * string * IFormatProvider -> string
type: int
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
type: Globalization.NumberStyles
inherits: Enum
inherits: ValueType
type Int32 =
struct
member CompareTo : obj -> int
member CompareTo : int -> int
member Equals : obj -> bool
member Equals : int -> bool
member GetHashCode : unit -> int
member GetTypeCode : unit -> System.TypeCode
member ToString : unit -> string
member ToString : string -> string
member ToString : System.IFormatProvider -> string
member ToString : string * System.IFormatProvider -> string
static val MaxValue : int
static val MinValue : int
static member Parse : string -> int
static member Parse : string * System.Globalization.NumberStyles -> int
static member Parse : string * System.IFormatProvider -> int
static member Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> int
static member TryParse : string * int -> bool
static member TryParse : string * System.Globalization.NumberStyles * System.IFormatProvider * int -> bool
end
Full name: System.Int32
type: Int32
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
--------------------
Int32()
Int32.Parse(s: string) : int
Int32.Parse(s: string, provider: IFormatProvider) : int
Int32.Parse(s: string, style: Globalization.NumberStyles) : int
Int32.Parse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider) : int
Full name: Script.IntegerZ5Associations.Init
from Microsoft.FSharp.Math
Full name: Microsoft.FSharp.Math.GlobalAssociations.RegisterNumericAssociation
module Matrix
from Microsoft.FSharp.Math
--------------------
type Matrix<'T>
with
interface Collections.Generic.IEnumerable<'T>
interface Collections.IStructuralEquatable
interface Collections.IStructuralComparable
interface IComparable
member Column : index:int -> Vector<'T>
member Columns : start:int * length:int -> Matrix<'T>
member Copy : unit -> Matrix<'T>
override Equals : obj -> bool
member GetDiagonal : int -> Vector<'T>
override GetHashCode : unit -> int
member GetSlice : start1:int option * finish1:int option * start2:int option * finish2:int option -> Matrix<'T>
member PermuteColumns : permutation:(int -> int) -> Matrix<'T>
member PermuteRows : permutation:(int -> int) -> Matrix<'T>
member Region : starti:int * startj:int * lengthi:int * lengthj:int -> Matrix<'T>
member Row : index:int -> RowVector<'T>
member Rows : start:int * length:int -> Matrix<'T>
member SetSlice : start1:int option * finish1:int option * start2:int option * finish2:int option * source:Matrix<'T> -> unit
member ToArray2 : unit -> 'T [,]
member ToArray2D : unit -> 'T [,]
member ToRowVector : unit -> RowVector<'T>
member ToVector : unit -> Vector<'T>
member Diagonal : Vector<'T>
member Dimensions : int * int
member ElementOps : INumeric<'T>
member InternalDenseValues : 'T [,]
member InternalSparseColumnValues : int []
member InternalSparseRowOffsets : int []
member InternalSparseValues : 'T []
member IsDense : bool
member IsSparse : bool
member Item : int * int -> 'T with get
member NonZeroEntries : seq<int * int * 'T>
member Norm : float
member NumCols : int
member NumRows : int
member StructuredDisplayAsArray : obj
member Transpose : Matrix<'T>
member Item : int * int -> 'T with set
static member ( + ) : Matrix<'T> * Matrix<'T> -> Matrix<'T>
static member ( .* ) : Matrix<'T> * Matrix<'T> -> Matrix<'T>
static member ( * ) : 'T * Matrix<'T> -> Matrix<'T>
static member ( * ) : Matrix<'T> * 'T -> Matrix<'T>
static member ( * ) : Matrix<'T> * Vector<'T> -> Vector<'T>
static member ( * ) : Matrix<'T> * Matrix<'T> -> Matrix<'T>
static member ( - ) : Matrix<'T> * Matrix<'T> -> Matrix<'T>
static member ( ~- ) : Matrix<'T> -> Matrix<'T>
static member ( ~+ ) : Matrix<'T> -> Matrix<'T>
end
Full name: Microsoft.FSharp.Math.Matrix<_>
type: Matrix<'T>
implements: Collections.Generic.IEnumerable<'T>
implements: Collections.IEnumerable
implements: Collections.IStructuralEquatable
implements: Collections.IStructuralComparable
implements: IComparable
from Microsoft.FSharp.Math.MatrixModule
from Script
Full name: Script.Script2.ys
type: Matrix<IntegerZ5>
implements: Collections.Generic.IEnumerable<IntegerZ5>
implements: Collections.IEnumerable
implements: Collections.IStructuralEquatable
implements: Collections.IStructuralComparable
implements: IComparable
Full name: Microsoft.FSharp.Math.MatrixModule.Generic.init
Full name: Script.Script2.xs
type: Matrix<IntegerZ5>
implements: Collections.Generic.IEnumerable<IntegerZ5>
implements: Collections.IEnumerable
implements: Collections.IStructuralEquatable
implements: Collections.IStructuralComparable
implements: IComparable
type SealedAttribute =
class
inherit System.Attribute
new : unit -> SealedAttribute
new : value:bool -> SealedAttribute
member Value : bool
end
Full name: Microsoft.FSharp.Core.SealedAttribute
type: SealedAttribute
implements: System.Runtime.InteropServices._Attribute
inherits: System.Attribute
--------------------
new : unit -> SealedAttribute
--------------------
new : value:bool -> SealedAttribute
with
member ToInt32 : unit -> int
override ToString : unit -> string
static member Create : int -> IntegerZ5
static member One : IntegerZ5
static member Zero : IntegerZ5
static member ( + ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( * ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
static member ( - ) : IntegerZ5 * IntegerZ5 -> IntegerZ5
end
Full name: FSharp.Numerics.IntegerZ5
Full name: FSharp.Numerics.IntegerZ5.ToInt32
Full name: Microsoft.FSharp.Core.unit
type: unit
implements: System.IComparable
val int : 'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
type: int<'Measure>
implements: System.IComparable
implements: System.IConvertible
implements: System.IFormattable
implements: System.IComparable<int<'Measure>>
implements: System.IEquatable<int<'Measure>>
inherits: System.ValueType
Full name: FSharp.Numerics.IntegerZ5.ToString
val string : 'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
Full name: FSharp.Numerics.IntegerZ5.Create
Full name: FSharp.Numerics.IntegerZ5.One
Full name: FSharp.Numerics.IntegerZ5.Zero
from FSharp.Numerics
Full name: FSharp.Numerics.NumericLiteralZ.FromZero
Full name: FSharp.Numerics.NumericLiteralZ.FromOne
Full name: FSharp.Numerics.NumericLiteralZ.FromInt32
Full name: FSharp.Numerics.NumericLiteralZ.FromInt64
val int64 : 'T -> int64 (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int64
--------------------
type int64 = System.Int64
Full name: Microsoft.FSharp.Core.int64
type: int64
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int64>
implements: System.IEquatable<int64>
inherits: System.ValueType
--------------------
type int64<'Measure> = int64
Full name: Microsoft.FSharp.Core.int64<_>
type: int64<'Measure>
implements: System.IComparable
implements: System.IConvertible
implements: System.IFormattable
implements: System.IComparable<int64<'Measure>>
implements: System.IEquatable<int64<'Measure>>
inherits: System.ValueType
from FSharp.Numerics
Full name: FSharp.Numerics.IntegerZ5TopLevelOperations.z5
from FSharp.Numerics
Full name: FSharp.Numerics.IntegerZ5Associations.IntegerZ5Numerics
type INumeric<'T> =
interface
abstract member Abs : 'T -> 'T
abstract member Add : 'T * 'T -> 'T
abstract member Compare : 'T * 'T -> int
abstract member Equals : 'T * 'T -> bool
abstract member Multiply : 'T * 'T -> 'T
abstract member Negate : 'T -> 'T
abstract member Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> 'T
abstract member Sign : 'T -> int
abstract member Subtract : 'T * 'T -> 'T
abstract member ToString : 'T * string * System.IFormatProvider -> string
abstract member One : 'T
abstract member Zero : 'T
end
Full name: Microsoft.FSharp.Math.INumeric<_>
--------------------
INumeric
Full name: FSharp.Numerics.IntegerZ5Associations.Init
Published: Thursday, 24 November 2011, 7:21 PM
Author: Tomas Petricek
Typos: Send me a pull request!
Tags: functional, f#, math and numerics