+
+
diff --git a/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nupkg b/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nupkg
new file mode 100644
index 00000000..6eb045c4
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nupkg differ
diff --git a/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nuspec b/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nuspec
new file mode 100644
index 00000000..9a63739e
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/FSharp.Formatting.1.0.15.nuspec
@@ -0,0 +1,19 @@
+
+
+
+ FSharp.Formatting
+ 1.0.15
+ FSharp.Formatting
+ Tomas Petricek, Oleg Pestov, Anh-Dung Phan
+ Tomas Petricek, Oleg Pestov, Anh-Dung Phan
+ http://github.com/tpetricek/FSharp.Formatting/blob/master/LICENSE.md
+ http://github.com/tpetricek/FSharp.Formatting
+ https://raw.github.com/tpetricek/FSharp.Formatting/master/docs/misc/logo.png
+ false
+ Provides an F# implementation of Markdown parser and F# code formatter that can used to tokenize F# code and obtain information about tokens including tool tips with type information. The package comes with a sample that implements literate programming for F#.
+ Added latex support, tables and better formatting with line numbers
+ Copyright 2013
+
+ F# fsharp formatting markdown code fssnip literate programming
+
+
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.dll b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.dll
new file mode 100644
index 00000000..4b2b5280
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.dll differ
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.pdb b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.pdb
new file mode 100644
index 00000000..5cbad6d2
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CodeFormat.pdb differ
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.dll b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.dll
new file mode 100644
index 00000000..33b7ba76
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.dll differ
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.pdb b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.pdb
new file mode 100644
index 00000000..4d2c72cf
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.CompilerBinding.pdb differ
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.dll b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.dll
new file mode 100644
index 00000000..4342306b
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.dll differ
diff --git a/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.pdb b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.pdb
new file mode 100644
index 00000000..26d895d3
Binary files /dev/null and b/packages/FSharp.Formatting.1.0.15/lib/net40/FSharp.Markdown.pdb differ
diff --git a/packages/FSharp.Formatting.1.0.15/literate/StringParsing.fs b/packages/FSharp.Formatting.1.0.15/literate/StringParsing.fs
new file mode 100644
index 00000000..4e5e2956
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/StringParsing.fs
@@ -0,0 +1,160 @@
+// --------------------------------------------------------------------------------------
+// F# Markdown (StringParsing.fs)
+// (c) Tomas Petricek, 2012, Available under Apache 2.0 license.
+// --------------------------------------------------------------------------------------
+
+module FSharp.Patterns
+
+open System
+open FSharp.Collections
+
+// --------------------------------------------------------------------------------------
+// Active patterns that simplify parsing of strings and lists of strings (lines)
+// --------------------------------------------------------------------------------------
+
+module String =
+ /// Matches when a string is a whitespace or null
+ let (|WhiteSpace|_|) s =
+ if String.IsNullOrWhiteSpace(s) then Some() else None
+
+ /// Matches when a string does starts with non-whitespace
+ let (|Unindented|_|) (s:string) =
+ if not (String.IsNullOrWhiteSpace(s)) && s.TrimStart() = s then Some() else None
+
+ /// Returns a string trimmed from both start and end
+ let (|TrimBoth|) (text:string) = text.Trim()
+ /// Returns a string trimmed from the end
+ let (|TrimEnd|) (text:string) = text.TrimEnd()
+ /// Returns a string trimmed from the start
+ let (|TrimStart|) (text:string) = text.TrimStart()
+
+ /// Retrusn a string trimmed from the end using characters given as a parameter
+ let (|TrimEndUsing|) chars (text:string) = text.TrimEnd(Array.ofSeq chars)
+
+ /// Returns a string trimmed from the start together with
+ /// the number of skipped whitespace characters
+ let (|TrimStartAndCount|) (text:string) =
+ let trimmed = text.TrimStart()
+ text.Length - trimmed.Length, trimmed
+
+ /// Matches when a string starts with any of the specified sub-strings
+ let (|StartsWithAny|_|) (starts:seq) (text:string) =
+ if starts |> Seq.exists (text.StartsWith) then Some() else None
+ /// Matches when a string starts with the specified sub-string
+ let (|StartsWith|_|) (start:string) (text:string) =
+ if text.StartsWith(start) then Some(text.Substring(start.Length)) else None
+ /// Matches when a string starts with the specified sub-string
+ /// The matched string is trimmed from all whitespace.
+ let (|StartsWithTrim|_|) (start:string) (text:string) =
+ if text.StartsWith(start) then Some(text.Substring(start.Length).Trim()) else None
+
+ /// Matches when a string starts with the given value and ends
+ /// with a given value (and returns the rest of it)
+ let (|StartsAndEndsWith|_|) (starts, ends) (s:string) =
+ if s.StartsWith(starts) && s.EndsWith(ends) &&
+ s.Length >= starts.Length + ends.Length then
+ Some(s.Substring(starts.Length, s.Length - starts.Length - ends.Length))
+ else None
+
+ /// Matches when a string starts with the given value and ends
+ /// with a given value (and returns trimmed body)
+ let (|StartsAndEndsWithTrim|_|) args = function
+ | StartsAndEndsWith args (TrimBoth res) -> Some res
+ | _ -> None
+
+ /// Matches when a string starts with a non-zero number of complete
+ /// repetitions of the specified parameter (and returns the number
+ /// of repetitions, together with the rest of the string)
+ ///
+ /// let (StartsWithRepeated "/\" (2, " abc")) = "/\/\ abc"
+ ///
+ let (|StartsWithRepeated|_|) (repeated:string) (text:string) =
+ let rec loop i =
+ if i = text.Length then i
+ elif text.[i] <> repeated.[i % repeated.Length] then i
+ else loop (i + 1)
+
+ let n = loop 0
+ if n = 0 || n % repeated.Length <> 0 then None
+ else Some(n/repeated.Length, text.Substring(n, text.Length - n))
+
+ /// Matches when a string starts with a sub-string wrapped using the
+ /// opening and closing sub-string specified in the parameter.
+ /// For example "[aa]bc" is wrapped in [ and ] pair. Returns the wrapped
+ /// text together with the rest.
+ let (|StartsWithWrapped|_|) (starts:string, ends:string) (text:string) =
+ if text.StartsWith(starts) then
+ let id = text.IndexOf(ends, starts.Length)
+ if id >= 0 then
+ let wrapped = text.Substring(starts.Length, id - starts.Length)
+ let rest = text.Substring(id + ends.Length, text.Length - id - ends.Length)
+ Some(wrapped, rest)
+ else None
+ else None
+
+ /// Matches when a string consists of some number of
+ /// complete repetitions of a specified sub-string.
+ let (|EqualsRepeated|_|) repeated = function
+ | StartsWithRepeated repeated (n, "") -> Some()
+ | _ -> None
+
+module List =
+ /// Matches a list if it starts with a sub-list that is delimited
+ /// using the specified delimiters. Returns a wrapped list and the rest.
+ let inline (|DelimitedWith|_|) startl endl input =
+ if List.startsWith startl input then
+ match List.partitionUntilEquals endl (List.skip startl.Length input) with
+ | Some(pre, post) -> Some(pre, List.skip endl.Length post)
+ | None -> None
+ else None
+
+ /// Matches a list if it starts with a sub-list that is delimited
+ /// using the specified delimiter. Returns a wrapped list and the rest.
+ let inline (|Delimited|_|) str = (|DelimitedWith|_|) str str
+
+ /// Matches a list if it starts with a bracketed list. Nested brackets
+ /// are skipped (by counting opening and closing brackets) and can be
+ /// escaped using the '\' symbol.
+ let (|BracketDelimited|_|) startc endc input =
+ let rec loop acc count = function
+ | '\\'::x::xs when x = endc -> loop (x::acc) count xs
+ | x::xs when x = endc && count = 0 -> Some(List.rev acc, xs)
+ | x::xs when x = endc -> loop (x::acc) (count - 1) xs
+ | x::xs when x = startc -> loop (x::acc) (count + 1) xs
+ | x::xs -> loop (x::acc) count xs
+ | [] -> None
+ match input with
+ | x::xs when x = startc -> loop [] 0 xs
+ | _ -> None
+
+ /// Retruns a list of characters as a string.
+ let (|AsString|) chars = String(Array.ofList chars)
+
+module Lines =
+ /// Removes blank lines from the start and the end of a list
+ let (|TrimBlank|) lines =
+ lines
+ |> List.skipWhile String.IsNullOrWhiteSpace |> List.rev
+ |> List.skipWhile String.IsNullOrWhiteSpace |> List.rev
+
+ /// Matches when there are some lines at the beginning that are
+ /// either empty (or whitespace) or start with the specified string.
+ /// Returns all such lines from the beginning until a different line.
+ let (|TakeStartingWithOrBlank|_|) start input =
+ match List.partitionWhile (fun s ->
+ String.IsNullOrWhiteSpace s || s.StartsWith(start)) input with
+ | matching, rest when matching <> [] -> Some(matching, rest)
+ | _ -> None
+
+ /// Removes whitespace lines from the beginning of the list
+ let (|TrimBlankStart|) = List.skipWhile (String.IsNullOrWhiteSpace)
+
+
+/// Parameterized pattern that assigns the specified value to the
+/// first component of a tuple. Usage:
+///
+/// match str with
+/// | Let 1 (n, "one") | Let 2 (n, "two") -> n
+///
+let (|Let|) a b = (a, b)
+
diff --git a/packages/FSharp.Formatting.1.0.15/literate/content/style.css b/packages/FSharp.Formatting.1.0.15/literate/content/style.css
new file mode 100644
index 00000000..e549557d
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/content/style.css
@@ -0,0 +1,152 @@
+@import url(http://fonts.googleapis.com/css?family=Ovo);
+@import url(http://fonts.googleapis.com/css?family=Droid+Sans+Mono);
+
+/*********************** TOOL TIP STYLES **********************/
+/* The following CSS classes are used by the F# formatter and */
+/* so you should include them whenever you want to display */
+/* HTML code generated by FSharp.CodeFormat.dll */
+/**************************************************************/
+
+/* identifier */
+span.i { color:#000000; }
+/* comment */
+span.c { color:#008000; }
+/* inactive code */
+span.inactive { color:#808080; }
+/* keywords */
+span.k { color:#000080; }
+/* numbers */
+span.n { color:#008000; }
+/* operators */
+span.o { color:#800080; }
+/* preprocessor */
+span.prep { color:#800080; }
+/* string */
+span.s { color:#808000; }
+/* line number */
+span.l { color:#80b0b0; }
+/* fsi output */
+span.fsi { font-style:italic; color:#606060; }
+/* omitted */
+span.omitted {
+ border:solid 1px #d8d8d8;
+ color:#808080;
+ padding:0px 0px 1px 0px;
+ background:#fafafa;
+}
+/* tool tip */
+div.tip
+{
+ font: 10pt calibri, sans-serif;
+ padding:3px;
+ border:1px solid #606060;
+ background:#ffffd0;
+ display:none;
+}
+
+/* Optionally, also configure how the PRE element and TABLE.PRE look */
+table.pre pre {
+ padding:0px;
+ margin:0px;
+ border-style:none;
+}
+
+pre, table.pre td {
+ padding:9.5px;
+ background:#f5f5f5;
+ border:solid 1px black;
+ border-radius:4px;
+ border-color:rgba(0,0,0,0.15);
+ margin:0px 0px 10px 0px;
+}
+
+table.pre td.lines {
+ border-top-right-radius:0px;
+ border-bottom-right-radius:0px;
+ border-right-style: none;
+ padding-right:0px;
+}
+table.pre td.snippet {
+ border-top-left-radius:0px;
+ border-bottom-left-radius:0px;
+ border-left-style: none;
+ padding-left:4px;
+}
+
+code, pre, pre code {
+ font-family:9pt "Droid Sans Mono", sans-serif;
+ line-height:13pt;
+}
+
+/********************* ADDITIONAL STYLES **********************/
+/* These styles are not necessary - they just provide a nice */
+/* Bootstrap template that can be freely used by F# libraries */
+/**************************************************************/
+
+body {
+ font-family: Ovo, serif;
+ padding-top: 0px;
+ padding-bottom: 40px;
+}
+
+/* Format the heading - nicer spacing etc. */
+.masthead {
+ overflow: hidden;
+}
+.masthead ul, .masthead li {
+ margin-bottom:0px;
+}
+.masthead .nav li {
+ margin-top: 15px;
+ font-size:110%;
+}
+.masthead h3 {
+ margin-bottom:5px;
+ font-size:170%;
+}
+hr {
+ margin:0px 0px 20px 0px;
+}
+
+/* Format the right-side menu */
+#menu {
+ margin-top:50px;
+ font-size:11pt;
+ padding-left:20px;
+}
+
+#menu .nav-header {
+ font-size:12pt;
+ color:#606060;
+ margin-top:20px;
+}
+
+#menu li {
+ line-height:25px;
+}
+
+/* Change font sizes for headings etc. */
+#main h1 { font-size: 26pt; margin:10px 0px 15px 0px; }
+#main h2 { font-size: 20pt; margin:20px 0px 0px 0px; }
+#main h3 { font-size: 14pt; margin:15px 0px 0px 0px; }
+#main p { font-size: 12pt; margin:5px 0px 15px 0px; }
+#main ul { font-size: 12pt; margin-top:10px; }
+#main li { font-size: 12pt; margin: 5px 0px 5px 0px; }
+
+/* Additional formatting for the homepage */
+#nuget {
+ margin-top:20px;
+ font-size: 11pt;
+ padding:20px;
+}
+
+#nuget pre {
+ font-size:11pt;
+ -moz-border-radius: 0px;
+ -webkit-border-radius: 0px;
+ border-radius: 0px;
+ background: #404040;
+ border-style:none;
+ color: #e0e0e0;
+ margin-top:15px;
+}
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/literate/content/tips.js b/packages/FSharp.Formatting.1.0.15/literate/content/tips.js
new file mode 100644
index 00000000..28ed18f6
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/content/tips.js
@@ -0,0 +1,47 @@
+var currentTip = null;
+var currentTipElement = null;
+
+function hideTip(evt, name, unique)
+{
+ var el = document.getElementById(name);
+ el.style.display = "none";
+ currentTip = null;
+}
+
+function findPos(obj)
+{
+ var curleft = 0;
+ var curtop = obj.offsetHeight;
+ while (obj)
+ {
+ curleft += obj.offsetLeft;
+ curtop += obj.offsetTop;
+ obj = obj.offsetParent;
+ };
+ return [curleft, curtop];
+}
+
+function hideUsingEsc(e)
+{
+ if (!e) { e = event; }
+ hideTip(e, currentTipElement, currentTip);
+}
+
+function showTip(evt, name, unique, owner)
+{
+ document.onkeydown = hideUsingEsc;
+ if (currentTip == unique) return;
+ currentTip = unique;
+ currentTipElement = name;
+
+ var pos = findPos(owner ? owner : (evt.srcElement ? evt.srcElement : evt.target));
+ var posx = pos[0];
+ var posy = pos[1];
+
+ var el = document.getElementById(name);
+ var parent = (document.documentElement == null) ? document.body : document.documentElement;
+ el.style.position = "absolute";
+ el.style.left = posx + "px";
+ el.style.top = posy + "px";
+ el.style.display = "block";
+}
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/literate/demo.fsx b/packages/FSharp.Formatting.1.0.15/literate/demo.fsx
new file mode 100644
index 00000000..e7a00850
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/demo.fsx
@@ -0,0 +1,41 @@
+// Given a typical setup (with 'FSharp.Formatting' referenced using NuGet),
+// the following will include binaries and load the literate script
+#I "../bin"
+#load "literate.fsx"
+open FSharp.Literate
+
+/// This functions processes a single F# Script file
+let processScript templateFile outputKind =
+ let file = __SOURCE_DIRECTORY__ + "\\test.fsx"
+ let output = __SOURCE_DIRECTORY__ + "\\outputs\\test." + (outputKind.ToString())
+ let template = __SOURCE_DIRECTORY__ + templateFile
+ Literate.ProcessScriptFile(file, template, output, format = outputKind)
+
+/// This functions processes a single Markdown document
+let processDocument templateFile outputKind =
+ let file = __SOURCE_DIRECTORY__ + "\\demo.md"
+ let output = __SOURCE_DIRECTORY__ + "\\outputs\\demo." + (outputKind.ToString())
+ let template = __SOURCE_DIRECTORY__ + templateFile
+ Literate.ProcessMarkdown(file, template, output, format = outputKind)
+
+/// This functions processes an entire directory containing
+/// multiple script files (*.fsx) and Markdown documents (*.md)
+/// and it specifies additional replacements for the template file
+let processDirectory() =
+ let dir = __SOURCE_DIRECTORY__
+ let template = __SOURCE_DIRECTORY__ + "\\templates\\template-project.html"
+ let projInfo =
+ [ "page-description", "F# Literate Programming"
+ "page-author", "Tomas Petricek"
+ "github-link", "https://github.com/tpetricek/FSharp.Formatting"
+ "project-name", "F# Formatting" ]
+
+ Literate.ProcessDirectory
+ ( dir, template, dir + "\\output", OutputKind.Html,
+ replacements = projInfo)
+
+// Generate output for sample scripts & documents in both HTML & Latex
+processScript "\\templates\\template-file.html" OutputKind.Html
+processDocument "\\templates\\template-file.html" OutputKind.Html
+processScript "\\templates\\template-color.tex" OutputKind.Latex
+processDocument "\\templates\\template-color.tex" OutputKind.Latex
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/literate/literate.fsx b/packages/FSharp.Formatting.1.0.15/literate/literate.fsx
new file mode 100644
index 00000000..594da4e4
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/literate.fsx
@@ -0,0 +1,717 @@
+(**
+Literate programming for F#
+===========================
+
+Implementation
+--------------
+
+This document is written as a literate F# script file, so the remaining text
+is an overview of the implementation. The implementation uses `FSharp.Markdown.dll`
+and `FSharp.CodeFormat.dll` to colorize F# source & parse Markdown:
+*)
+
+(*** hide ***)
+namespace FSharp.Literate
+#if INTERACTIVE
+#I "../bin/"
+#r "System.Web.dll"
+#r "FSharp.Markdown.dll"
+#r "FSharp.CodeFormat.dll"
+#load "StringParsing.fs"
+#endif
+
+open System
+open System.IO
+open System.Web
+open System.Reflection
+open System.Collections.Generic
+
+open FSharp.Patterns
+open FSharp.CodeFormat
+open FSharp.Markdown
+
+(**
+### OutputKind type
+
+The following type defines the two possible output types from literate script:
+HTML and LaTeX.
+
+*)
+[]
+type OutputKind =
+ | Html
+ | Latex
+ (*[omit:(members omitted)]*)
+
+ /// Name of the format (used as a file extension)
+ override x.ToString() =
+ match x with
+ | Html -> "html"
+ | Latex -> "tex"
+
+ /// Format a given document as HTML or LaTeX depending on the current kind
+ member x.Format(doc) =
+ match x with
+ | OutputKind.Html -> Markdown.WriteHtml(doc)
+ | OutputKind.Latex -> Markdown.WriteLatex(doc)
+
+ /// The name of the {tag} that is used for pasting content into a template file
+ /// (the default is {document}, but that collides in LaTeX)
+ member x.ContentTag =
+ match x with
+ | OutputKind.Html -> "document"
+ | OutputKind.Latex -> "contents"
+ (*[/omit]*)
+
+(**
+### CommandUtils module
+
+Utilities for parsing commands. Commands can be used in different places. We
+recognize `key1=value, key2=value` and also `key1:value, key2:value`
+*)
+module internal CommandUtils =
+ (*[omit:(Implementation omitted)]*)
+
+ let (|ParseCommands|_|) (str:string) =
+ let kvs =
+ [ for cmd in str.Split(',') do
+ let kv = cmd.Split([| '='; ':' |])
+ if kv.Length = 2 then yield kv.[0].Trim(), kv.[1].Trim()
+ elif kv.Length = 1 then yield kv.[0].Trim(), "" ]
+ if kvs <> [] then Some(dict kvs) else None
+
+ let (|Command|_|) k (d:IDictionary<_, _>) =
+ match d.TryGetValue(k) with
+ | true, v -> Some v
+ | _ -> None
+ (*[/omit]*)
+
+(**
+### LiterateUtils module
+
+Utilities for processing Markdown documents - extract links for references,
+add links to references, extract code blocks for colorization and replace them
+with formatted HTML (after running F# code formatter)
+*)
+module internal LiterateUtils =
+ (*[omit:(Implementation omitted)]*)
+ open CommandUtils
+
+ /// Given Markdown document, get the keys of all IndirectLinks
+ /// (to be used when generating paragraph with all references)
+ let rec collectReferences =
+
+ // Collect IndirectLinks in a span
+ let rec collectSpanReferences span = seq {
+ match span with
+ | IndirectLink(_, _, key) -> yield key
+ | Matching.SpanLeaf _ -> ()
+ | Matching.SpanNode(_, spans) ->
+ for s in spans do yield! collectSpanReferences s }
+
+ // Collect IndirectLinks in a paragraph
+ let rec loop par = seq {
+ match par with
+ | Matching.ParagraphLeaf _ -> ()
+ | Matching.ParagraphNested(_, pars) ->
+ for ps in pars do
+ for p in ps do yield! loop p
+ | Matching.ParagraphSpans(_, spans) ->
+ for s in spans do yield! collectSpanReferences s }
+ loop
+
+ /// Given Markdown document, add a number using the given index to all indirect
+ /// references. For example, [article][ref] becomes [article][ref] [1](#rfxyz)
+ let replaceReferences (refIndex:IDictionary) =
+
+ // Replace IndirectLinks with a nice link given a single span element
+ let rec replaceSpans = function
+ | IndirectLink(body, original, key) ->
+ [ yield IndirectLink(body, original, key)
+ match refIndex.TryGetValue(key) with
+ | true, i ->
+ yield Literal " ["
+ yield DirectLink([Literal (string i)], ("#rf" + DateTime.Now.ToString("yyMMddhh"), None))
+ yield Literal "]"
+ | _ -> () ]
+ | Matching.SpanLeaf(sl) -> [Matching.SpanLeaf(sl)]
+ | Matching.SpanNode(nd, spans) ->
+ [ Matching.SpanNode(nd, List.collect replaceSpans spans) ]
+
+ // Given a paragraph, process it recursively and transform all spans
+ let rec loop = function
+ | Matching.ParagraphNested(pn, nested) ->
+ Matching.ParagraphNested(pn, List.map (List.choose loop) nested) |> Some
+ | Matching.ParagraphSpans(ps, spans) ->
+ Matching.ParagraphSpans(ps, List.collect replaceSpans spans) |> Some
+ | Matching.ParagraphLeaf(pl) -> Matching.ParagraphLeaf(pl) |> Some
+ loop
+
+ /// Iterate over Markdown document and extract all F# code snippets that we want
+ /// to colorize. We skip snippets that specify non-fsharp langauge e.g. [lang=csharp].
+ let rec collectCodeSnippets par = seq {
+ match par with
+ | CodeBlock(String.StartsWithWrapped ("[", "]") (ParseCommands cmds, String.TrimStart code))
+ when cmds.ContainsKey("lang") && cmds.["lang"] <> "fsharp" -> ()
+ | CodeBlock(String.StartsWithWrapped ("[", "]") (ParseCommands cmds, String.TrimStart code))
+ | CodeBlock(Let (dict []) (cmds, code)) ->
+ let modul =
+ match cmds.TryGetValue("module") with
+ | true, v -> Some v | _ -> None
+ yield modul, code
+ | Matching.ParagraphLeaf _ -> ()
+ | Matching.ParagraphNested(_, pars) ->
+ for ps in pars do
+ for p in ps do yield! collectCodeSnippets p
+ | Matching.ParagraphSpans(_, spans) -> () }
+
+ /// Replace CodeBlock elements with formatted HTML that was processed by the F# snippets tool
+ /// (The dictionary argument is a map from original code snippets to formatted HTML snippets.)
+ let rec replaceCodeSnippets outputKind (codeLookup:IDictionary<_, _>) = function
+ | CodeBlock(String.StartsWithWrapped ("[", "]") (ParseCommands cmds, String.TrimStart code))
+ when cmds.ContainsKey("hide") -> None
+ | CodeBlock(String.StartsWithWrapped ("[", "]") (ParseCommands cmds, String.TrimStart code))
+ | CodeBlock(Let (dict []) (cmds, code)) ->
+ if (cmds.ContainsKey("lang")) && cmds.["lang"] <> "fsharp" then
+ let content =
+ if outputKind = OutputKind.Html then
+ "
" + HttpUtility.HtmlEncode(code) + "
"
+ else sprintf "\\begin{lstlisting}\n%s\n\\end{lstlisting}" <| HttpUtility.HtmlDecode(code)
+ HtmlBlock(content) |> Some
+ else
+ let content : string = codeLookup.[code]
+ HtmlBlock(content) |> Some
+
+ // Recursively process nested paragraphs, other nodes return without change
+ | Matching.ParagraphNested(pn, nested) ->
+ let pars = List.map (List.choose (replaceCodeSnippets outputKind codeLookup)) nested
+ Matching.ParagraphNested(pn, pars) |> Some
+ | other -> Some other
+
+ /// Try find first-level heading in the paragraph collection
+ let findHeadings paragraphs (outputKind:OutputKind) =
+ paragraphs |> Seq.tryPick (function
+ | (Heading(1, text)) ->
+ let doc = MarkdownDocument([Span(text)], dict [])
+ Some(outputKind.Format(doc))
+ | _ -> None)
+ (*[/omit]*)
+
+(**
+### CodeBlockUtils module
+
+Parsing of F# Script files with Markdown commands. Given a parsed script file, we
+split it into a sequence of comments, snippets and commands (comment starts with
+`(**` and ending with `*)` are translated to Markdown, snippet is all other F# code
+and command looks like `(*** key1:value, key2:value ***)` (and should be single line).
+*)
+module internal CodeBlockUtils =
+ (*[omit:(Implementation omitted)]*)
+ open CommandUtils
+
+ type Block =
+ | BlockComment of string
+ | BlockSnippet of Line list
+ | BlockCommand of IDictionary
+
+ /// Trim blank lines from both ends of a lines list & reverse it (we accumulate
+ /// lines & we want to remove all blanks before returning BlockSnippet)
+ let private trimBlanksAndReverse lines =
+ lines
+ |> Seq.skipWhile (function Line[] -> true | _ -> false)
+ |> List.ofSeq |> List.rev
+ |> Seq.skipWhile (function Line[] -> true | _ -> false)
+ |> List.ofSeq
+
+ /// Succeeds when a line (list of tokens) contains only Comment
+ /// tokens and returns the text from the comment as a string
+ let private (|ConcatenatedComments|_|) (Line tokens) =
+ let comments =
+ tokens |> List.choose (function
+ | Token(TokenKind.Comment, text, _) -> Some text
+ | _ -> None)
+ if comments.Length <> tokens.Length then None
+ else Some (String.concat "" comments)
+
+ // Process lines of an F# script file. Simple state machine with two states
+ // * collectComment - we're parsing a comment and waiting for the end
+ // * collectSnippet - we're in a normal F# code and we're waiting for a comment
+ // (in both states, we also need to recognize (*** commands ***)
+
+ /// Waiting for the end of a comment
+ let rec private collectComment (comment:string) lines = seq {
+ match lines with
+ | (ConcatenatedComments(String.StartsAndEndsWith ("(***", "***)") (ParseCommands cmds)))::lines ->
+ // Ended with a command, yield comment, command & parse the next as a snippet
+ let cend = comment.LastIndexOf("*)")
+ yield BlockComment (comment.Substring(0, cend))
+ yield BlockCommand cmds
+ yield! collectSnippet [] lines
+
+ | (ConcatenatedComments text)::_ when
+ comment.LastIndexOf("*)") <> -1 && text.Trim().StartsWith("//") ->
+ // Comment ended, but we found a code snippet starting with // comment
+ let cend = comment.LastIndexOf("*)")
+ yield BlockComment (comment.Substring(0, cend))
+ yield! collectSnippet [] lines
+
+ | (Line[Token(TokenKind.Comment, String.StartsWith "(**" text, _)])::lines ->
+ // Another block of Markdown comment starting...
+ // Yield the previous snippet block and continue parsing more comments
+ let cend = comment.LastIndexOf("*)")
+ yield BlockComment (comment.Substring(0, cend))
+ if lines <> [] then yield! collectComment text lines
+
+ | (ConcatenatedComments text)::lines ->
+ // Continue parsing comment
+ yield! collectComment (comment + "\n" + text) lines
+
+ | lines ->
+ // Ended - yield comment & continue parsing snippet
+ let cend = comment.LastIndexOf("*)")
+ yield BlockComment (comment.Substring(0, cend))
+ if lines <> [] then yield! collectSnippet [] lines }
+
+ /// Collecting a block of F# snippet
+ and private collectSnippet acc lines = seq {
+ match lines with
+ | (ConcatenatedComments(String.StartsAndEndsWith ("(***", "***)") (ParseCommands cmds)))::lines ->
+ // Found a special command, yield snippet, command and parse another snippet
+ if acc <> [] then yield BlockSnippet (trimBlanksAndReverse acc)
+ yield BlockCommand cmds
+ yield! collectSnippet [] lines
+
+ | (Line[Token(TokenKind.Comment, String.StartsWith "(**" text, _)])::lines ->
+ // Found a comment - yield snippet & switch to parsing comment state
+ if acc <> [] then yield BlockSnippet (trimBlanksAndReverse acc)
+ yield! collectComment text lines
+
+ | x::xs -> yield! collectSnippet (x::acc) xs
+ | [] -> yield BlockSnippet (trimBlanksAndReverse acc) }
+
+ /// Parse F# script file into a sequence of snippets, comments and commands
+ let parseScriptFile = collectSnippet []
+
+ /// Given a parsed script file, extract "definitions". A definition is a part of
+ /// the file that we want to include elsewhere (and hide in the original location):
+ ///
+ /// (*** define:key ***)
+ /// let foo = 1 + 2
+ ///
+ /// This function returns 'string * Block' list containing all definitions
+ /// together with all a list of all remaining blocks that were not extracted.
+ let extractDefinitions defns =
+ let rec loop defns normal = function
+ | [] -> defns, normal |> List.rev
+ | BlockCommand(Command "hide" _)::(BlockSnippet _)::rest ->
+ loop defns normal rest
+ | BlockCommand(Command "define" key)::(BlockSnippet lines)::rest ->
+ // If we have command with 'define' in it, then pick the following
+ // snippet (it should be a snippet) and return it as a definition
+ loop ((key, lines)::defns) normal rest
+ | current::rest ->
+ loop defns (current::normal) rest
+ defns |> List.ofSeq |> loop [] []
+ (*[/omit]*)
+
+(**
+### SourceProcessors module
+
+Functions that process `*.fsx` and `*.md` files. The function `processScriptFile`
+assumes that the file is an F# script file (with text hidden in comments) while
+`processMarkdown` assumes that all F# code is included as code snippets.
+*)
+module internal SourceProcessors =
+
+ /// Specifies a context that is passed to the
+ /// code/document processing functions
+ type ProcessingContext =
+ { // An instance of the F# code formatting agent
+ FormatAgent : CodeFormatAgent
+ // Source code of a HTML template file
+ Template : string option
+ // Short prefix code added to all HTML 'id' elements
+ Prefix : string
+ // Should the processing add 'References' section?
+ GenerateReferences : bool
+ // Additional replacements to be made in the template file
+ Replacements : list
+ // Generate line numbers for F# snippets?
+ GenerateLineNumbers : bool
+ // Include the source file in the generated output as '{source}'
+ IncludeSource : bool
+ // Command line options for the F# compiler
+ Options : string
+ // The output format
+ OutputKind : OutputKind
+ // Custom function for reporting errors
+ ErrorHandler : option unit> }
+
+ (*[omit:(Implementation omitted)]*)
+ open CommandUtils
+ open CodeBlockUtils
+ open LiterateUtils
+
+ /// Print information about all errors during the processing
+ let private reportErrors ctx file (errors:seq) =
+ match ctx.ErrorHandler with
+ | Some eh -> for e in errors do eh(file, e)
+ | _ ->
+ for (SourceError((sl, sc), (el, ec), kind, msg)) in errors do
+ printfn " * (%d:%d)-(%d:%d) (%A): %s" sl sc el ec kind msg
+ if Seq.length errors > 0 then printfn ""
+
+ /// Given all links defined in the Markdown document and a list of all links
+ /// that are accessed somewhere from the document, generate References paragraph
+ let generateReferences (definedLinks:IDictionary<_, string * string option>) refs outputKind =
+
+ // For all unique references in the document,
+ // get the link & title from definitions
+ let refs =
+ refs |> set |> Seq.choose (fun ref ->
+ match definedLinks.TryGetValue(ref) with
+ | true, (link, Some title) -> Some (ref, link, title)
+ | _ -> None)
+ |> Seq.sort |> Seq.mapi (fun i v -> i+1, v)
+ // Generate dictionary with a number for all references
+ let refLookup = dict [ for (i, (r, _, _)) in refs -> r, i ]
+
+ // Generate Markdown blocks paragraphs representing Reference
items
+ let refList =
+ [ for i, (ref, link, title) in refs do
+ let colon = title.IndexOf(":")
+ if colon > 0 then
+ let auth = title.Substring(0, colon)
+ let name = title.Substring(colon + 1, title.Length - 1 - colon)
+ yield [Span [ Literal (sprintf "[%d] " i)
+ DirectLink([Literal name], (link, Some title))
+ Literal (" - " + auth)] ]
+ else
+ yield [Span [ Literal (sprintf "[%d] " i)
+ DirectLink([Literal title], (link, Some title))]] ]
+
+ // Return the document together with dictionary for looking up indices
+ let literal =
+ match outputKind with
+ | OutputKind.Html ->
+ // Return the document together with dictionary for looking up indices
+ let id = DateTime.Now.ToString("yyMMddhh")
+ Literal ("References")
+ | OutputKind.Latex ->
+ // Add formatting later
+ Literal ("References")
+ [ Heading(3, [literal])
+ ListBlock(MarkdownListKind.Unordered, refList) ], refLookup
+
+ /// Replace {parameter} in the input string with
+ /// values defined in the specified list
+ let replaceParameters parameters input =
+ match input with
+ | None ->
+ // If there is no template, return just document + tooltips
+ let lookup = parameters |> dict
+ lookup.["document"] + "\n\n" + lookup.["tooltips"]
+ | Some input ->
+ // First replace keys with some uglier keys and then replace them with values
+ // (in case one of the keys appears in some other value)
+ let id = System.Guid.NewGuid().ToString("d")
+ let input = parameters |> Seq.fold (fun (html:string) (key, value) ->
+ html.Replace("{" + key + "}", "{" + key + id + "}")) input
+ let result = parameters |> Seq.fold (fun (html:string) (key, value) ->
+ html.Replace("{" + key + id + "}", value)) input
+ result
+
+ /// Write formatted blocks to a specified string builder
+ /// and return first-level heading if there is some
+ let outputBlocks (sb:Text.StringBuilder)
+ // Original blocks of the input document
+ blocks
+ // Sequence with just formatted BlockSnippet elements
+ (snippets:seq)
+ // Sequence with just formatted BlockComment elements
+ (comments:seq)
+ (definitions:IDictionary<_, string>) refLookup outputKind =
+
+ // We traverse sequences using enumerators as we need them
+ let heading = ref None
+ use snippetsEn = snippets.GetEnumerator()
+ use commentsEn = comments.GetEnumerator()
+ let nextSnippet () = snippetsEn.MoveNext() |> ignore; snippetsEn.Current
+ let nextComment () = commentsEn.MoveNext() |> ignore; commentsEn.Current
+
+ for block in blocks do
+ match block with
+ // Skip known commands and comments ('hide' is removed in earlier step)
+ | BlockCommand (Command "include" key) -> sb.Append(definitions.[key]) |> ignore
+ | BlockCommand (Command "define" _) -> ()
+ | BlockCommand cmds when cmds.Count = 1 && cmds.Keys |> Seq.head |> Seq.forall ((=) '*') -> ()
+ | BlockCommand cmds ->
+ failwithf "Unsupported command: %s" (String.concat ", " [ for (KeyValue(k,v)) in cmds -> k + ":" + v ])
+
+ // Emit next comment, but search for headings
+ | BlockComment s ->
+ let mdoc = nextComment()
+ let paragraphs = mdoc.Paragraphs |> List.choose (replaceReferences refLookup)
+ findHeadings paragraphs outputKind |> Option.iter (fun v -> heading := Some v)
+ let doc = MarkdownDocument(paragraphs, mdoc.DefinedLinks)
+ sb.Append(outputKind.Format(doc)) |> ignore
+
+ // Emit next snippet (if it is not just empty list)
+ | BlockSnippet lines ->
+ let snip = nextSnippet()
+ if lines <> [] then sb.Append(snip.Content) |> ignore
+ !heading
+
+ // ------------------------------------------------------------------------------------
+
+ /// Process F# Script file
+ let processScriptFile ctx file output =
+ let name = Path.GetFileNameWithoutExtension(file)
+
+ // Parse the entire file as an F# script file,
+ // get sequence of blocks & extract definitions
+ let sourceSnippets, errors = ctx.FormatAgent.ParseSource(file, File.ReadAllText(file), ctx.Options)
+ reportErrors ctx file errors
+ let (Snippet(_, lines)) = match sourceSnippets with [| it |] -> it | _ -> failwith "multiple snippets"
+ let definitions, blocks = parseScriptFile lines |> extractDefinitions
+
+ // Process all definitions & build a dictionary with HTML for each definition
+ let snippets = [| for name, lines in definitions -> Snippet(name, lines) |]
+ let formattedDefns =
+ match ctx.OutputKind with
+ | OutputKind.Html -> CodeFormat.FormatHtml(snippets, ctx.Prefix + "d", ctx.GenerateLineNumbers, false)
+ | OutputKind.Latex -> CodeFormat.FormatLatex(snippets, ctx.GenerateLineNumbers)
+ let definitions = dict [ for snip in formattedDefns.Snippets -> snip.Title, snip.Content ]
+
+ // Process all snippet blocks in the script file (using F# formatter)
+ let snippets = blocks |> List.choose (function
+ | BlockSnippet(lines) -> Some(Snippet("Untitled", lines))
+ | _ -> None) |> Array.ofList
+ let formatted =
+ match ctx.OutputKind with
+ | OutputKind.Html -> CodeFormat.FormatHtml(snippets, ctx.Prefix, ctx.GenerateLineNumbers, false)
+ | OutputKind.Latex -> CodeFormat.FormatLatex(snippets, ctx.GenerateLineNumbers)
+
+ // Parse all comment blocks in the script file (as Markdown)
+ let parsedBlocks = blocks |> Array.ofSeq |> Seq.choose (function
+ | BlockComment(text) -> Some(Markdown.Parse(text))
+ | _ -> None)
+
+ // Turn all indirect links into a references & add paragraph to the document
+ let refParagraph, refLookup =
+ if ctx.GenerateReferences then
+ // Union link definitions & collect all indirect links
+ let definedLinks = parsedBlocks |> Seq.collect (fun mdoc ->
+ [ for (KeyValue(k, v)) in mdoc.DefinedLinks -> k, v]) |> dict
+ let refs = parsedBlocks |> Seq.collect (fun mdoc ->
+ Seq.collect collectReferences mdoc.Paragraphs)
+ let pars, refLookup = generateReferences definedLinks refs ctx.OutputKind
+ Some pars, refLookup
+ else None, dict []
+
+ // Write all HTML content to a string builder & add References
+ let sb = Text.StringBuilder()
+ let heading = outputBlocks sb blocks formatted.Snippets parsedBlocks definitions refLookup ctx.OutputKind
+ refParagraph |> Option.iter (fun p ->
+ let output = ctx.OutputKind.Format(MarkdownDocument(p, dict []))
+ sb.Append(output) |> ignore)
+
+ // If we want to include the source code of the script, then process
+ // the entire source and generate replacement {source} => ...some html...
+ let sourceReplacement, sourceTips =
+ match ctx.OutputKind with
+ | OutputKind.Html ->
+ if ctx.IncludeSource then
+ let formatted = CodeFormat.FormatHtml(sourceSnippets, ctx.Prefix + "s")
+ let content =
+ match formatted.Snippets with
+ | [| snip |] -> snip.Content
+ | snips -> [ for s in snips -> sprintf "
%s
\n%s" s.Title s.Content ] |> String.concat ""
+ [ "source", content ], formatted.ToolTip
+ else [], ""
+ | OutputKind.Latex ->
+ if ctx.IncludeSource then
+ let formatted = CodeFormat.FormatLatex(sourceSnippets)
+ let content =
+ match formatted.Snippets with
+ | [| snip |] -> snip.Content
+ | snips -> [ for s in snips -> sprintf "\subsubsection{%s}\n%s" s.Title s.Content ] |> String.concat ""
+ [ "source", content ], formatted.ToolTip
+ else [], ""
+
+ // Replace all parameters in the template & write to output
+ let parameters =
+ ctx.Replacements @ sourceReplacement @
+ [ "page-title", defaultArg heading name
+ ctx.OutputKind.ContentTag, sb.ToString()
+ "tooltips", formatted.ToolTip + formattedDefns.ToolTip + sourceTips ]
+ File.WriteAllText(output, replaceParameters parameters ctx.Template)
+
+ // ------------------------------------------------------------------------------------
+
+ /// Process Markdown document
+ let processMarkdown ctx file output =
+ // Read file & parse Markdown document
+ let name = Path.GetFileNameWithoutExtension(file)
+ let originalSource = File.ReadAllText(file)
+ let doc = Markdown.Parse(originalSource)
+
+ // Turn all indirect links into a references & add paragraph to the document
+ let refParagraph, refLookup =
+ if ctx.GenerateReferences then
+ // Union link definitions & collect all indirect links
+ let refs = Seq.collect collectReferences doc.Paragraphs
+ let pars, refLookup = generateReferences doc.DefinedLinks refs ctx.OutputKind
+ Some pars, refLookup
+ else None, dict []
+
+ // Extract all CodeBlocks and pass them to F# snippets
+ let codes = doc.Paragraphs |> Seq.collect collectCodeSnippets |> Array.ofSeq
+ let codeLookup, tipsHtml =
+ if codes.Length = 0 then dict [], ""
+ else
+ // If there are some F# snippets, we build an F# source file
+ let blocks = codes |> Seq.mapi (fun index (modul, code) ->
+ match modul with
+ | Some modul ->
+ // generate module & add indentation
+ "module " + modul + " =\n" +
+ "// [snippet:" + (string index) + "]\n" +
+ " " + code.Replace("\n", "\n ") + "\n" +
+ "// [/snippet]"
+ | None ->
+ "// [snippet:" + (string index) + "]\n" +
+ code + "\n" +
+ "// [/snippet]" )
+
+ // Process F# script file, report errors & build lookup table for replacement
+ let modul = "module " + (new String(name |> Seq.filter Char.IsLetter |> Seq.toArray))
+ let source = modul + "\r\n" + (String.concat "\n\n" blocks)
+ let snippets, errors = ctx.FormatAgent.ParseSource(output + ".fs", source, ctx.Options)
+ reportErrors ctx file errors
+ let formatted =
+ match ctx.OutputKind with
+ | OutputKind.Html -> CodeFormat.FormatHtml(snippets, ctx.Prefix, ctx.GenerateLineNumbers, false)
+ | OutputKind.Latex -> CodeFormat.FormatLatex(snippets, ctx.GenerateLineNumbers)
+ let snippetLookup =
+ [ for (_, code), fs in Array.zip codes formatted.Snippets -> code, fs.Content ]
+ dict snippetLookup, formatted.ToolTip
+
+ // Process all paragraphs in two steps (replace F# snippets & references)
+ let paragraphs =
+ doc.Paragraphs |> List.choose (fun par ->
+ par |> replaceCodeSnippets ctx.OutputKind codeLookup
+ |> Option.bind (replaceReferences refLookup))
+
+ // If we want to include the source code of the script, then process
+ // the entire source and generate replacement {source} => ...some html...
+ let sourceReplacements =
+ if ctx.IncludeSource then
+ let doc = MarkdownDocument([CodeBlock originalSource], dict [])
+ let content = ctx.OutputKind.Format(doc)
+ [ "source", content ]
+ else []
+
+ // Construct new Markdown document and write it
+ let parameters =
+ ctx.Replacements @ sourceReplacements @
+ [ "page-title", defaultArg (findHeadings paragraphs ctx.OutputKind) name
+ ctx.OutputKind.ContentTag, ctx.OutputKind.Format(MarkdownDocument(paragraphs, doc.DefinedLinks))
+ "tooltips", tipsHtml ]
+ File.WriteAllText(output, replaceParameters parameters ctx.Template)
+ (*[/omit]*)
+
+
+(**
+
+## Public API
+
+The following type provides three simple methods for calling the literate programming tool.
+The `ProcessMarkdown` and `ProcessScriptFile` methods process a single Markdown document
+and F# script, respectively. The `ProcessDirectory` method handles an entire directory tree
+(looking for `*.fsx` and `*.md` files).
+*)
+open SourceProcessors
+
+type Literate =
+ (*[omit:(Helper methdods omitted)]*)
+ /// Provides default values for all optional parameters
+ static member private DefaultArguments
+ ( input, templateFile, output,format, fsharpCompiler, prefix, compilerOptions,
+ lineNumbers, references, replacements, includeSource, errorHandler) =
+ let defaultArg v f = match v with Some v -> v | _ -> f()
+
+ let outputKind = defaultArg format (fun _ -> OutputKind.Html)
+
+ let output = defaultArg output (fun () ->
+ let dir = Path.GetDirectoryName(input)
+ let file = Path.GetFileNameWithoutExtension(input)
+ Path.Combine(dir, sprintf "%s.%O" file outputKind))
+ let fsharpCompiler = defaultArg fsharpCompiler (fun () ->
+ Assembly.Load("FSharp.Compiler"))
+
+ // Build & return processing context
+ let ctx =
+ { FormatAgent = CodeFormat.CreateAgent(fsharpCompiler)
+ Template = templateFile |> Option.map (fun file -> File.ReadAllText(file))
+ Prefix = defaultArg prefix (fun () -> "fs")
+ Options = defaultArg compilerOptions (fun () -> "")
+ GenerateLineNumbers = defaultArg lineNumbers (fun () -> true)
+ GenerateReferences = defaultArg references (fun () -> false)
+ Replacements = defaultArg replacements (fun () -> [])
+ IncludeSource = defaultArg includeSource (fun () -> false)
+ OutputKind = outputKind
+ ErrorHandler = errorHandler }
+ output, ctx(*[/omit]*)
+
+ /// Process Markdown document
+ static member ProcessMarkdown
+ ( input, ?templateFile, ?output, ?format, ?fsharpCompiler, ?prefix, ?compilerOptions,
+ ?lineNumbers, ?references, ?replacements, ?includeSource, ?errorHandler ) = (*[omit:(...)]*)
+ let output, ctx =
+ Literate.DefaultArguments
+ ( input, templateFile, output, format, fsharpCompiler, prefix, compilerOptions,
+ lineNumbers, references, replacements, includeSource, errorHandler )
+ processMarkdown ctx input output (*[/omit]*)
+
+ /// Process F# Script file
+ static member ProcessScriptFile
+ ( input, ?templateFile, ?output, ?format, ?fsharpCompiler, ?prefix, ?compilerOptions,
+ ?lineNumbers, ?references, ?replacements, ?includeSource, ?errorHandler ) = (*[omit:(...)]*)
+ let output, ctx =
+ Literate.DefaultArguments
+ ( input, templateFile, output, format, fsharpCompiler, prefix, compilerOptions,
+ lineNumbers, references, replacements, includeSource, errorHandler )
+ processScriptFile ctx input output (*[/omit]*)
+
+ /// Process directory containing a mix of Markdown documents and F# Script files
+ static member ProcessDirectory
+ ( inputDirectory, ?templateFile, ?outputDirectory, ?format, ?fsharpCompiler, ?prefix, ?compilerOptions,
+ ?lineNumbers, ?references, ?replacements, ?includeSource, ?errorHandler ) = (*[omit:(...)]*)
+ let _, ctx =
+ Literate.DefaultArguments
+ ( "", templateFile, Some "", format, fsharpCompiler, prefix, compilerOptions,
+ lineNumbers, references, replacements, includeSource, errorHandler )
+
+ /// Recursively process all files in the directory tree
+ let rec processDirectory indir outdir =
+ // Create output directory if it does not exist
+ if Directory.Exists(outdir) |> not then
+ try Directory.CreateDirectory(outdir) |> ignore
+ with _ -> failwithf "Cannot create directory '%s'" outdir
+
+ let fsx = [ for f in Directory.GetFiles(indir, "*.fsx") -> processScriptFile, f ]
+ let mds = [ for f in Directory.GetFiles(indir, "*.md") -> processMarkdown, f ]
+ for func, file in fsx @ mds do
+ let name = Path.GetFileNameWithoutExtension(file)
+ let output = Path.Combine(outdir, sprintf "%s.%O" name ctx.OutputKind)
+
+ // Update only when needed
+ let changeTime = File.GetLastWriteTime(file)
+ let generateTime = File.GetLastWriteTime(output)
+ if changeTime > generateTime then
+ printfn "Generating '%s.%O'" name ctx.OutputKind
+ func ctx file output
+
+ let outputDirectory = defaultArg outputDirectory inputDirectory
+ processDirectory inputDirectory outputDirectory (*[/omit]*)
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/literate/templates/template-file.html b/packages/FSharp.Formatting.1.0.15/literate/templates/template-file.html
new file mode 100644
index 00000000..c1a7e77c
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/templates/template-file.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+ {page-title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {document}
+ {tooltips}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/FSharp.Formatting.1.0.15/literate/templates/template-project.html b/packages/FSharp.Formatting.1.0.15/literate/templates/template-project.html
new file mode 100644
index 00000000..f6803c9a
--- /dev/null
+++ b/packages/FSharp.Formatting.1.0.15/literate/templates/template-project.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+ {page-title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/repositories.config b/packages/repositories.config
index dc9d9a50..f7c3c813 100644
--- a/packages/repositories.config
+++ b/packages/repositories.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/src/FSharp/Distributions.fs b/src/FSharp/Distributions.fs
index f32a0765..53aa354f 100644
--- a/src/FSharp/Distributions.fs
+++ b/src/FSharp/Distributions.fs
@@ -35,13 +35,13 @@ open MathNet.Numerics.Random
[]
module Sample =
- let transform f dist : System.Random -> 'T = fun rng -> f (dist rng)
- let transform2 f dist1 dist2 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng)
- let transform3 f dist1 dist2 dist3 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng) (dist3 rng)
+ let map f dist : System.Random -> 'T = fun rng -> f (dist rng)
+ let map2 f dist1 dist2 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng)
+ let map3 f dist1 dist2 dist3 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng) (dist3 rng)
- let transformSeq f dist : System.Random -> 'T seq = fun rng -> dist rng |> Seq.map f
- let transformSeq2 f dist1 dist2 : System.Random -> 'T seq = fun rng -> Seq.zip (dist1 rng) (dist2 rng) |> Seq.map (fun (d1, d2) -> f d1 d2)
- let transformSeq3 f dist1 dist2 dist3 : System.Random -> 'T seq = fun rng -> Seq.zip3 (dist1 rng) (dist2 rng) (dist3 rng) |> Seq.map (fun (d1, d2, d3) -> f d1 d2 d3)
+ let mapSeq f dist : System.Random -> 'T seq = fun rng -> dist rng |> Seq.map f
+ let mapSeq2 f dist1 dist2 : System.Random -> 'T seq = fun rng -> Seq.zip (dist1 rng) (dist2 rng) |> Seq.map (fun (d1, d2) -> f d1 d2)
+ let mapSeq3 f dist1 dist2 dist3 : System.Random -> 'T seq = fun rng -> Seq.zip3 (dist1 rng) (dist2 rng) (dist3 rng) |> Seq.map (fun (d1, d2, d3) -> f d1 d2 d3)
/// Bernoulli with probability (p).
let bernoulli p rng = Bernoulli.Sample(rng, p)
diff --git a/src/FSharpExamples/FSharpExamples.fsproj b/src/FSharpExamples/FSharpExamples.fsproj
index a6ad6184..35476da1 100644
--- a/src/FSharpExamples/FSharpExamples.fsproj
+++ b/src/FSharpExamples/FSharpExamples.fsproj
@@ -52,9 +52,22 @@
+
+
+ ..\..\packages\FSharp.Formatting.1.0.15\lib\net40\FSharp.CodeFormat.dll
+ True
+
+
+ ..\..\packages\FSharp.Formatting.1.0.15\lib\net40\FSharp.CompilerBinding.dll
+ True
+
+
+ ..\..\packages\FSharp.Formatting.1.0.15\lib\net40\FSharp.Markdown.dll
+ True
+
diff --git a/src/FSharpExamples/Matrices.fsx b/src/FSharpExamples/Matrices.fsx
index 883f90ff..25c894d0 100644
--- a/src/FSharpExamples/Matrices.fsx
+++ b/src/FSharpExamples/Matrices.fsx
@@ -41,12 +41,12 @@ let a1 = DenseMatrix(2, 3, [| 1.0; 2.0; 10.0; 20.0; 100.0; 300.0 |])
let a2 = DenseMatrix.raw 2 3 [| 1.0; 2.0; 10.0; 20.0; 100.0; 300.0 |]
// Create a matrix of size 3x4 (3 rows, 4 columns) with a given number for each value
-let b1 = DenseMatrix.zeroCreate 3 4
+let b1 : float Matrix = DenseMatrix.zero 3 4
let b2 = DenseMatrix.create 3 4 20.5
-let b3 = SparseMatrix.zeroCreate 3 4
+let b3 : float Matrix = SparseMatrix.zero 3 4
// Create a matrix of size 3x4 with random values sampled from a distribution
-let c = DenseMatrix.randomCreate 3 4 (Normal.WithMeanStdDev(2.0, 0.5))
+let c : float Matrix = DenseMatrix.random 3 4 (Normal.WithMeanStdDev(2.0, 0.5))
// Create a matrix of size 3x4 with each value initialized by a lambda function
let d1 = DenseMatrix.init 3 4 (fun i j -> float i / 100.0 + float j)
diff --git a/src/FSharpExamples/RandomAndDistributions.fsx b/src/FSharpExamples/RandomAndDistributions.fsx
index d56d4ff3..538cbfb9 100644
--- a/src/FSharpExamples/RandomAndDistributions.fsx
+++ b/src/FSharpExamples/RandomAndDistributions.fsx
@@ -1,30 +1,34 @@
(**
+Random Numbers and Probability Distributions
+============================================
-Math.NET Numerics: Random Numbers and Probability Distributions
-===============================================================
-
-The .Net base class library provides a pseudo-random number generator
-for non-cryptography use in the form of the `System.Numerics` class.
+The .Net Framework base class library includes a pseudo-random number generator
+for non-cryptography use in the form of the `System.Random` class.
Math.NET Numerics provides a few alternatives with different characteristics
in randomness, bias, sequence length and performance. All these classes
-inherit from System.Random so you can use them as a replacement for
-System.Random even in third-party code.
+inherit from `System.Random` so you can use them as a drop-in replacement
+even in third-party code.
+
+All random number generators (RNG) generate numbers in a more-or-less uniform
+distribution. In practice you often need to sample random numbers with a different
+distribution, like a Gaussian or Poisson. You can do that with one of our probability
+distribution classes, or in F# also using the `Sample` module. Once parametrized,
+the distribution classes also provide a variety of other functionality around probability
+distributions, like evaluating statistical distribution properties or functions.
-All random number generators generate numbers in a more-or-less uniform
-distribution. Often you need to sample random numbers with a different
-distribution, e.g. a Gaussian. You can do that with one of the distribution
-classes, or in F# also using the `Sample` module. The distribution classes
-also provide a lot of other functionality around probability distributions,
-like parameter estimation or evaluating the commulative distribution function.
+Initialization
+--------------
-Initializtation
----------------
+We need to reference Math.NET Numerics and open the namespaces for
+random numbers and probability distributions:
-We need to reference Math.NET Numerics and the F# modules, and open
-the namespaces for random numbers and probability distributions:
+ using MathNet.Numerics.Random;
+ using MathNet.Numerics.Distributions;
+Or in F#:
*)
+// Only needed in scripts/interactive
#r "../../out/lib/Net40/MathNet.Numerics.dll"
#r "../../out/lib/Net40/MathNet.Numerics.FSharp.dll"
@@ -32,47 +36,85 @@ open MathNet.Numerics.Random
open MathNet.Numerics.Distributions
(**
-
Random Number Generators
------------------------
+Let's sample a few uniform random values using Mersenne Twister in C#:
+
+ var rng = new MersenneTwister(42);
+ int randomInt = rng.Next();
+ double randomDouble = rng.NextDouble();
+
+In F# you can use the constructor as well, or alternatively use the `Random` module.
+In case of the latter, all objects will be cast to their common base type `System.Random`:
+*)
+
+let rng = MersenneTwister(42)
+let rngEx = Random.mersenneTwisterSeed 42
+let randomInt = rng.Next()
+
+(**
+If you have used `System.Random` before, you may remember that it only offers `Next` methods
+to sample integers, and `NextDouble` for floating point numbers in the [0,1) interval.
+Did you ever have a need to generate numbers of the full integer range including negative numbers,
+or a `System.Decimal`? Extending discrete random numbers to different ranges or types is non-trivial
+if the distribution should still be uniform over the chosen range. That's why we've added a few extensions
+methods which are available on all RNGs (including `System.Random` itself):
+*)
+
+let values =
+ ( rng.Next(), // built-in: int32 in the range [0, Int.MaxValue)
+ rng.NextInt64(), // int64 in the range [0, Long.MaxValue)
+ rng.NextFullRangeInt32(), // int32 in the range [Int.MinValue, Int.MaxValue]
+ rng.NextFullRangeInt64(), // int64 in the range [Long.MinValue, Long.MaxValue]
+ rng.NextDouble(), // built-in: double in the range [0.0, 1.0)
+ rng.NextDecimal() ) // decimal in then range [0.0, 1.0)
+
+(**
+The following custom RNGs are currently available in Math.NET Numerics:
+
+* `MersenneTwister`: Mersenne Twister 19937 generator
+* `Xorshift`: Multiply-with-carry XOR-shift generator
+* `Mcg31m1`: Multiplicative congruental generator using a modulus of 2^31-1 and a multiplier of 1132489760
+* `Mcg59`: Multiplicative congruental generator using a modulus of 2^59 and a multiplier of 13^13
+* `WH1982`: Wichmann-Hill's 1982 combined multiplicative congruental generator
+* `WH2006`: Wichmann-Hill's 2006 combined multiplicative congruental generator
+* `Mrg32k3a`: 32-bit combined multiple recursive generator with 2 components of order 3
+* `Palf`: Parallel Additive Lagged Fibonacci generator
+* `SystemCryptoRandomNumberGenerator`: Using the RNGCryptoServiceProvider of the .Net Framework. *Not available in portable builds.*
+
+Seeds and Thread Safety
+-----------------------
+
Other than for cryptographic random numbers where you'd never want to provide
-a seed, all pseudo-random numbers can be initialized with a custom seed.
-The same seed causes the same number sequence to be generated, which can be
-very useful if you need results to be reproducible, e.g. in testing/verification.
+a seed, all other RNGs can be initialized with a custom seed. In the code sample
+above we've used `42` as seed. The same seed causes the same number sequence
+to be generated, which can be very useful if you need results to be reproducible,
+e.g. in testing/verification.
-If no seed is provided, System.Random uses a time based seed equivalent to the
+If no seed is provided, `System.Random` uses a time based seed equivalent to the
one below. This means that all instances created within a short timeframe
-(which typically spans around a thousand CPU clock cycles) will generate
+(which typically spans about a thousand CPU clock cycles) will generate
exactly the same sequence. This can happen easily e.g. in parallel computing
and is often unwanted. That's why all number generators created using
Math.NET Numerics routines are by default initialized with a seed that combines
the time with a Guid (which are supposed to be generated uniquely, worldwide).
-
*)
let someTimeSeed = RandomSeed.Time()
let someGuidSeed = RandomSeed.Guid()
(**
-
-Random number generators can be created using the `Random` module. Most functions
-optionally accept a manual seed when using the variant with the Seed-suffix.
-Some of them, like xor-shift, also have a variant with a Custom-suffix that
-allow to pass additional parameters specific to that generator.
-
Note that the generators should be reused when generating multiple numbers.
If you'd create a new generator each time, the numbers it generates would be
exactly as random as your seed - and thus not very random at all.
-However, generators are not automatically thread-safe. They *are* thread-safe
-in Math.NET Numerics by default, but that can be disabled either using a
-boolean argument at creation, or by setting `Control.ThreadSafeRandomNumberGenerators`.
-
+However, generators are not automatically thread-safe in .Net. They *are* thread-safe
+when created using Math.NET Numerics by default, but that can be controlled either by a
+boolean argument at creation or by setting `Control.ThreadSafeRandomNumberGenerators`.
*)
let a = Random.system ()
-let b = Random.systemSeed (RandomSeed.Time())
-let b2 = Random.systemSeed someGuidSeed
+let b = Random.systemSeed (RandomSeed.Guid())
let c = Random.crypto ()
let d = Random.mersenneTwister ()
let e = Random.mersenneTwisterWith 1000 true (* thread-safe *)
@@ -81,28 +123,24 @@ let g = Random.xorshiftCustom someTimeSeed false 916905990L 13579L 362436069L 77
let h = Random.wh2006 ()
let i = Random.palf ()
-// Generate some uniform random values
-let values = (
- a.Next(),
- b.NextFullRangeInt32(),
- c.NextFullRangeInt64(),
- d.NextInt64(),
- e.NextDouble(),
- f.NextDecimal()
- )
-
(**
-
Probability Distributions
-------------------------
-Non-uniform probability distributions can be created using their normal constructor,
-some also offer static functions if there are multiple ways to parametrize them.
+For non-uniform random number generation you can use one the wide range of probability
+distributions in the `MathNet.Numerics.Distributions` namespace.
+
+There are many ways to parametrize a distribution in the literature. When using the
+default constructor, read carefully which parameters it requires. For distributions where
+multiple ways are common there are also static methods, so you can use the one that fits best.
+For example, a normal distribution is usually parametrized with mean and standard deviation,
+but if you'd rather use mean and precision:
+
+ var normal = Normal.WithMeanPrecision(0.0, 0.5);
Since probability distributions can also be sampled to generate random numbers
with the configured distribution, all constructors optionally accept a random generator
-as last argument.
-
+as last argument. A few more examples, this time in F#:
*)
// some probability distributions
@@ -114,17 +152,15 @@ let poisson = Poisson(3.0)
let geometric = Geometric(0.8, Random.system())
// sample some random rumbers from these distributions
-let continuous = [
- yield normal.Sample()
- yield exponential.Sample()
- yield! gamma.Samples() |> Seq.take 10
- ]
-let discrete = [
- poisson.Sample()
- poisson.Sample()
- geometric.Sample()
- ]
+let continuous =
+ [ yield normal.Sample()
+ yield exponential.Sample()
+ yield! gamma.Samples() |> Seq.take 10 ]
+let discrete =
+ [ poisson.Sample()
+ poisson.Sample()
+ geometric.Sample() ]
// direct sampling (without creating a distribution object)
let u = Normal.Sample(Random.system(), 2.0, 4.0)
@@ -133,78 +169,85 @@ let w = Rayleigh.Sample(c, 1.5)
let x = Hypergeometric.Sample(h, 100, 20, 5)
(**
-
-Specifically for F# there is also a `Sample` module that allow a somewhat
-more functional view on the distributions by allowing them to be curried such that
-the random source is passed in as last arguments. This way distributions can
-be combined and transformed arbitrarily:
-
+Distribution Functions and Properties
+-------------------------------------
+
+Distributions can not just be used to generate non-uniform random samples.
+Once parametrized they can compute a variety of distribution properties
+or evaluate distribution functions. Because it is often numerically more stable
+and faster to compute and work with such quantities in the logarithmic domain,
+some of them are also available with the `Ln`-suffix.
*)
-/// Transform a sample distribution
-let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
-
-/// Alternative way where we transform the function instead of its result
-let s1alt rng = Sample.transform tanh (Sample.normal 2.0 0.5) rng
+// distribution properties of the gamma we've configured above
+let gammaStats =
+ ( gamma.Mean,
+ gamma.Variance,
+ gamma.StdDev,
+ gamma.Entropy,
+ gamma.Skewness,
+ gamma.Mode )
+
+// probability distribution functions of the normal we've configured above.
+let nd = normal.Density(4.0) (* pdf *)
+let ndLn = normal.DensityLn(4.0) (* ln(pdf) *)
+let nc = normal.CumulativeDistribution(4.0) (* cdf *)
+let nic = normal.InverseCumulativeDistribution(0.7) (* invcdf *)
-/// Alternative way that works exactly the same but operates on functions generating sequences
-let s1seq rng = Sample.transformSeq tanh (Sample.normalSeq 2.0 0.5) rng
+// Distribution functions can also be evaluated without creating an object,
+// but then you have to pass in the distribution parameters as first arguments:
+let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)
+let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)
+let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)
+let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)
-/// The same with multiple distributions:
-let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
-let s2alt rng = Sample.transform2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
-let s2seq rng = Sample.transformSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
+(**
+Some of the distributions also have routines for maximum-likelihood parameter
+estimation from a set of samples:
+*)
-Seq.take 10 (s2seq (Random.system())) |> Seq.toArray
+let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
+let mean, variance = estimation.Mean, estimation.Variance
+let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
(**
+or in C#:
-Let's do some random walks, using distributions and random sources defined above:
+ LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});
+ double mean = estimation.Mean, variance = estimation.Variance;
+ double[] moreSamples = estimation.Samples().Take(10).ToArray();
+Let's do some random walks, using distributions and random sources defined above (TODO: Graph):
*)
Seq.scan (+) 0.0 (normal.Samples()) |> Seq.take 10 |> Seq.toArray
Seq.scan (+) 0.0 (Sample.normalSeq 0.0 0.5 a) |> Seq.take 10 |> Seq.toArray
-Seq.scan (+) 0.0 (s1seq a) |> Seq.take 10 |> Seq.toArray
(**
+Composing Distributions
+-----------------------
-Distributions can not just be used to generate random samples.
-You can use them to evaluate distribution properties or functions
-with the given parametrization.
-
+Specifically for F# there is also a `Sample` module that allows a somewhat more functional
+view on distribution sampling functions by having the random source passed in as last argument.
+This way they can be composed and transformed arbitrarily if curried:
*)
-// distribution properties of the gamma dist we configured above
-let gammaStats = (
- gamma.Mean,
- gamma.Variance,
- gamma.StdDev,
- gamma.Entropy,
- gamma.Skewness,
- gamma.Mode
- )
-
-// probability distribution functions of the normal dist we configured above
-let nd = normal.Density(4.0) (* pdf *)
-let ndLn = normal.DensityLn(4.0) (* ln(pdf) *)
-let nc = normal.CumulativeDistribution(4.0) (* cdf *)
-let nic = normal.InverseCumulativeDistribution(0.7) (* invcdf *)
+/// Transform a sample from a distribution
+let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
-// Distribution functions can also be evaluated without creating an object,
-// but then you have to pass in the distribution parameters as first arguments:
-let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)
-let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)
-let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)
-let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)
+/// But we really want to transform the function, not the resulting sample:
+let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng
-(**
+/// Exactly the same also works with functions generating full sequences
+let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng
-Some of the distributions also have routines for maximum-likelihood parameter
-estimation from a set of samples:
+/// Now with multiple distributions, e.g. their product:
+let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
+let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
+let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
-*)
+// Taking some samples from the composed function
+Seq.take 10 (s2s (Random.system())) |> Seq.toArray
-let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
-let mean, variance = estimation.Mean, estimation.Variance
-let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
+// The random walk from above, but this time using the composition from above
+Seq.scan (+) 0.0 (s1s a) |> Seq.take 10 |> Seq.toArray
diff --git a/src/FSharpExamples/Vectors.fsx b/src/FSharpExamples/Vectors.fsx
index 2fd2111d..5e6692d0 100644
--- a/src/FSharpExamples/Vectors.fsx
+++ b/src/FSharpExamples/Vectors.fsx
@@ -40,12 +40,12 @@ let a1 = DenseVector [| 1.0; 2.0; 3.0 |]
let a2 = DenseVector.raw [| 1.0; 2.0; 3.0 |]
// Create a vector of length 100 with a given number for each value
-let b1 = DenseVector.zeroCreate 100
+let b1 : float Vector = DenseVector.zero 100
let b2 = DenseVector.create 100 20.5
-let b3 = SparseVector.zeroCreate 100
+let b3 : float Vector = SparseVector.zero 100
// Create a vector of length 100 with random values sampled from a distribution
-let c = DenseVector.randomCreate 100 (Normal.WithMeanStdDev(2.0, 0.5))
+let c : float Vector = DenseVector.random 100 (Normal.WithMeanStdDev(2.0, 0.5))
// Create a vector of length 100 with each value initialized by a lambda function
let d1 = DenseVector.init 100 (fun i -> float i / 100.0)
diff --git a/src/FSharpExamples/packages.config b/src/FSharpExamples/packages.config
new file mode 100644
index 00000000..854612a5
--- /dev/null
+++ b/src/FSharpExamples/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file