<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Matthew Manela&#039;s Home Page &#187; F#</title>
	<atom:link href="http://matthewmanela.com/category/f/feed/" rel="self" type="application/rss+xml" />
	<link>http://matthewmanela.com</link>
	<description>The life and work of Matthew Manela</description>
	<lastBuildDate>Sun, 25 Jul 2010 18:00:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Regex based Lexer with F#</title>
		<link>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f/</link>
		<comments>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 14:52:00 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">http://blogs.msdn.com/matt/archive/2010/01/19/regex-lexer-with-f.aspx</guid>
		<description><![CDATA[This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. open Lexer
let definitions = 
    lexerDefinitions {
        do! addNextlineDefinition "NEWLINE" @"(\n\r)&#124;\n&#124;\r"
        do!...]]></description>
			<content:encoded><![CDATA[<P>This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. </P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> definitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    lexerDefinitions {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NEWLINE</SPAN>" @"<SPAN style="COLOR: #8b0000">(\n\r)|\n|\r</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">WS</SPAN>"        @"<SPAN style="COLOR: #8b0000">\s</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">LET</SPAN>"             "<SPAN style="COLOR: #8b0000">let</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">ID</SPAN>"              "<SPAN style="COLOR: #8b0000">(?i)[a-z][a-z0-9]*</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">FLOAT</SPAN>"           @"<SPAN style="COLOR: #8b0000">[0-9]+\.[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">INT</SPAN>"             "<SPAN style="COLOR: #8b0000">[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">OPERATOR</SPAN>"      @"<SPAN style="COLOR: #8b0000">[+*=!/&amp;|&lt;&gt;\^\-]+</SPAN>"   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }</PRE></PRE>
<P>With those defined you can execute the lexer with:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> lex input = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">try</SPAN>    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN> y = Lexer.tokenize definitions input
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        printfn "<SPAN style="COLOR: #8b0000">%A</SPAN>" y
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">with</SPAN> e -&gt; printf "<SPAN style="COLOR: #8b0000">%s</SPAN>" e.Message
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">lex "<SPAN style="COLOR: #8b0000">let a = 5</SPAN>"</PRE></PRE>
<P>Which will result in:</P>
<BLOCKQUOTE>
<P align=left>seq [{name = "LET"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "let"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "ID"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "a"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "OPERATOR"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "="; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "INT"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "5"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}]</P></BLOCKQUOTE>
<P align=left>The lexer’s code is structured in three parts.&nbsp; The first part is a state monad using the F# computation expressions.&nbsp; This enables the declarative approach (seen above) to setup your lexer rules.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module StateMonad
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type State&lt;'s,'a&gt; = State of ('s -&gt; ('a *'s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> runState (State f) = f
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type StateBuilder() = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Return(x) = State (fun s -&gt; (x,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Delay(f) = f() : State&lt;'s,'a&gt;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Zero() = State (fun s -&gt; ((),s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Bind(State p,rest) = State (fun s -&gt; <SPAN style="COLOR: #0000ff">let</SPAN> v,s2 = p s <SPAN style="COLOR: #0000ff">in</SPAN>  (runState (rest v)) s2)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.<SPAN style="COLOR: #0000ff">Get</SPAN> () = State (fun s -&gt; (s,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Put s = State (fun _ -&gt; ((),s))</PRE></PRE>
<P>The second part are the combinators that are used to define your lexer rules.&nbsp; There are three main combinators:&nbsp; <STRONG>AddDefinition</STRONG> which lets you define a name / regex pair, <STRONG>AddIgnoreDefinition </STRONG>which lets you define characters which the lexer should ignore and <STRONG>AddNextlineDefinition </STRONG>which lets you define what characters determine a new line.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type LexDefinitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  {regexes : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   names : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   nextlines : bool list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   ignores : bool list; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> buildDefinition name pattern nextLine ignore =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN>! x = state.<SPAN style="COLOR: #0000ff">Get</SPAN>()
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! state.Put { regexes = x.regexes @  [sprintf @"<SPAN style="COLOR: #8b0000">(?&lt;%s&gt;%s)</SPAN>" name pattern];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        names = x.names @ [name]; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        nextlines  = x.nextlines @ [nextLine];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        ignores = x.ignores @ [ignore]}
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addDefinition name pattern = buildDefinition name pattern false false
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addIgnoreDefinition name pattern = buildDefinition name pattern false true
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addNextlineDefinition name pattern = buildDefinition name pattern true true    </PRE></PRE>
<P>And the final part is the code that performs the tokenizing.&nbsp; It uses the Seq.unfold method to create the list of tokens.&nbsp; Unfold is a function which takes a single item and generates a list of new items from it.&nbsp; It is the opposite of Seq.fold which takes a list of items and turns it into a single item.&nbsp; The tokenize function used Seq.unfold to generate each token while keeping track of the current line number, position in that line and position in the input string.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type Token = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    { name : <SPAN style="COLOR: #0000ff">string</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      text: <SPAN style="COLOR: #0000ff">string</SPAN>; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      pos :<SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      column: <SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      line: <SPAN style="COLOR: #0000ff">int</SPAN> }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> createLexDefs pb =  (runState pb) {regexes = []; names = []; nextlines = []; ignores = []} |&gt; snd
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"> 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> tokenize lexerBuilder (str:<SPAN style="COLOR: #0000ff">string</SPAN>) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> patterns = createLexDefs lexerBuilder
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> combinedRegex =  Regex(List.fold (fun acc reg -&gt; acc + "<SPAN style="COLOR: #8b0000">|</SPAN>" + reg) (List.head patterns.regexes) (List.tail patterns.regexes))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> nextlineMap = List.zip patterns.names patterns.nextlines |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ignoreMap = List.zip patterns.names patterns.ignores |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokenizeStep (pos,line,lineStart) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">if</SPAN> pos &gt;= str.Length <SPAN style="COLOR: #0000ff">then</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            None
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">else</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">let</SPAN> getMatchedGroupName (grps:GroupCollection) names = List.find (fun (name:<SPAN style="COLOR: #0000ff">string</SPAN>) -&gt; grps.[name].Length &gt; 0) names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">match</SPAN> combinedRegex.<SPAN style="COLOR: #0000ff">Match</SPAN>(str, pos) <SPAN style="COLOR: #0000ff">with</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | mt when mt.Success &amp;&amp; pos = mt.Index  -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> groupName = getMatchedGroupName mt.Groups patterns.names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> column = mt.Index - lineStart
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> nextPos = pos + mt.Length
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> (nextLine, nextLineStart) = <SPAN style="COLOR: #0000ff">if</SPAN> nextlineMap.Item groupName <SPAN style="COLOR: #0000ff">then</SPAN> (line + 1, nextPos) <SPAN style="COLOR: #0000ff">else</SPAN> (line,lineStart)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> token = <SPAN style="COLOR: #0000ff">if</SPAN> ignoreMap.Item groupName 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">then</SPAN> None 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">else</SPAN> Some {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        name = groupName; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        text = mt.Value; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        pos = pos; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        line = line; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        column = column; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    Some(token, (nextPos, nextLine, nextLineStart))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | otherwise -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> textAroundError = str.Substring(pos, min (pos + 5) str.Length)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    raise (ArgumentException (sprintf "<SPAN style="COLOR: #8b0000">Lexing error occured at line:%d and column:%d near the text:%s</SPAN>" line (pos - lineStart) textAroundError))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Seq.unfold tokenizeStep (0, 0, 0) |&gt; Seq.<SPAN style="COLOR: #0000ff">filter</SPAN> (fun x -&gt; x.IsSome) |&gt; Seq.map (fun x -&gt; x.Value)</PRE></PRE>
<P>Lastly, here are the unit tests written using <A href="http://xunit.codeplex.com/" mce_href="http://xunit.codeplex.com/">XUnit.Net</A>:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module LexerFacts
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Xunit
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open System.Linq
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> simpleDefs = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NextLine</SPAN>"           "<SPAN style="COLOR: #8b0000">/</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">IgnoredSymbol</SPAN>"        "<SPAN style="COLOR: #8b0000">=+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">String</SPAN>"                     "<SPAN style="COLOR: #8b0000">[a-zA-Z]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Number</SPAN>"                     "<SPAN style="COLOR: #8b0000">\d+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Name</SPAN>"                       "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_return_no_tokens_for_empty_string() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000"></SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_throw_exception_for_invalid_token() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">-</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ex = Assert.ThrowsDelegateWithReturn(fun () -&gt; upcast tokens.Count()) |&gt; Record.Exception
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.NotNull(ex)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.True(ex :? System.ArgumentException)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_ignore_symbols_defined_as_ignore_symbols() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">=========</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_get_token_with_correct_position_and_type() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one=2=two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_tokenize_string_with_alernating_numbers_and_strings() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">1</SPAN>",tokens.ElementAt(0).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">one</SPAN>",tokens.ElementAt(1).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">two</SPAN>",tokens.ElementAt(3).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_increment_line_with_newline_symbol() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one/2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(1,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_give_priority_to_lexer_definitions_defined_earlier() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">String</SPAN>",tokens.ElementAt(0).name)</PRE></PRE>
<P mce_keep="true">&nbsp;</P>
<P>I attached a zip (<A href="http://blogs.msdn.com/matt/attachment/9950348.ashx" mce_href="http://blogs.msdn.com/matt/attachment/9950348.ashx">Lexer.zip</A>) containing all the code mentioned above.</P><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9950348" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blogs.msdn.com/matt/attachment/9950348.ashx" length="2225" type="application/x-zip-compressed" />
		</item>
		<item>
		<title>Regex based Lexer with F#</title>
		<link>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-2/</link>
		<comments>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-2/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 14:52:00 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">/b/matt/archive/2010/01/19/regex-lexer-with-f.aspx</guid>
		<description><![CDATA[This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. open Lexer
let definitions = 
    lexerDefinitions {
        do! addNextlineDefinition "NEWLINE" @"(\n\r)&#124;\n&#124;\r"
        do!...]]></description>
			<content:encoded><![CDATA[<P>This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. </P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> definitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    lexerDefinitions {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NEWLINE</SPAN>" @"<SPAN style="COLOR: #8b0000">(\n\r)|\n|\r</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">WS</SPAN>"        @"<SPAN style="COLOR: #8b0000">\s</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">LET</SPAN>"             "<SPAN style="COLOR: #8b0000">let</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">ID</SPAN>"              "<SPAN style="COLOR: #8b0000">(?i)[a-z][a-z0-9]*</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">FLOAT</SPAN>"           @"<SPAN style="COLOR: #8b0000">[0-9]+\.[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">INT</SPAN>"             "<SPAN style="COLOR: #8b0000">[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">OPERATOR</SPAN>"      @"<SPAN style="COLOR: #8b0000">[+*=!/&amp;|&lt;&gt;\^\-]+</SPAN>"   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }</PRE></PRE>
<P>With those defined you can execute the lexer with:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> lex input = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">try</SPAN>    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN> y = Lexer.tokenize definitions input
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        printfn "<SPAN style="COLOR: #8b0000">%A</SPAN>" y
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">with</SPAN> e -&gt; printf "<SPAN style="COLOR: #8b0000">%s</SPAN>" e.Message
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">lex "<SPAN style="COLOR: #8b0000">let a = 5</SPAN>"</PRE></PRE>
<P>Which will result in:</P>
<BLOCKQUOTE>
<P align=left>seq [{name = "LET"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "let"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "ID"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "a"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "OPERATOR"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "="; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "INT"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "5"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}]</P></BLOCKQUOTE>
<P align=left>The lexer’s code is structured in three parts.&nbsp; The first part is a state monad using the F# computation expressions.&nbsp; This enables the declarative approach (seen above) to setup your lexer rules.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module StateMonad
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type State&lt;'s,'a&gt; = State of ('s -&gt; ('a *'s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> runState (State f) = f
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type StateBuilder() = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Return(x) = State (fun s -&gt; (x,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Delay(f) = f() : State&lt;'s,'a&gt;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Zero() = State (fun s -&gt; ((),s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Bind(State p,rest) = State (fun s -&gt; <SPAN style="COLOR: #0000ff">let</SPAN> v,s2 = p s <SPAN style="COLOR: #0000ff">in</SPAN>  (runState (rest v)) s2)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.<SPAN style="COLOR: #0000ff">Get</SPAN> () = State (fun s -&gt; (s,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Put s = State (fun _ -&gt; ((),s))</PRE></PRE>
<P>The second part are the combinators that are used to define your lexer rules.&nbsp; There are three main combinators:&nbsp; <STRONG>AddDefinition</STRONG> which lets you define a name / regex pair, <STRONG>AddIgnoreDefinition </STRONG>which lets you define characters which the lexer should ignore and <STRONG>AddNextlineDefinition </STRONG>which lets you define what characters determine a new line.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type LexDefinitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  {regexes : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   names : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   nextlines : bool list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   ignores : bool list; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> buildDefinition name pattern nextLine ignore =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN>! x = state.<SPAN style="COLOR: #0000ff">Get</SPAN>()
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! state.Put { regexes = x.regexes @  [sprintf @"<SPAN style="COLOR: #8b0000">(?&lt;%s&gt;%s)</SPAN>" name pattern];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        names = x.names @ [name]; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        nextlines  = x.nextlines @ [nextLine];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        ignores = x.ignores @ [ignore]}
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addDefinition name pattern = buildDefinition name pattern false false
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addIgnoreDefinition name pattern = buildDefinition name pattern false true
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addNextlineDefinition name pattern = buildDefinition name pattern true true    </PRE></PRE>
<P>And the final part is the code that performs the tokenizing.&nbsp; It uses the Seq.unfold method to create the list of tokens.&nbsp; Unfold is a function which takes a single item and generates a list of new items from it.&nbsp; It is the opposite of Seq.fold which takes a list of items and turns it into a single item.&nbsp; The tokenize function used Seq.unfold to generate each token while keeping track of the current line number, position in that line and position in the input string.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type Token = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    { name : <SPAN style="COLOR: #0000ff">string</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      text: <SPAN style="COLOR: #0000ff">string</SPAN>; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      pos :<SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      column: <SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      line: <SPAN style="COLOR: #0000ff">int</SPAN> }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> createLexDefs pb =  (runState pb) {regexes = []; names = []; nextlines = []; ignores = []} |&gt; snd
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"> 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> tokenize lexerBuilder (str:<SPAN style="COLOR: #0000ff">string</SPAN>) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> patterns = createLexDefs lexerBuilder
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> combinedRegex =  Regex(List.fold (fun acc reg -&gt; acc + "<SPAN style="COLOR: #8b0000">|</SPAN>" + reg) (List.head patterns.regexes) (List.tail patterns.regexes))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> nextlineMap = List.zip patterns.names patterns.nextlines |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ignoreMap = List.zip patterns.names patterns.ignores |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokenizeStep (pos,line,lineStart) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">if</SPAN> pos &gt;= str.Length <SPAN style="COLOR: #0000ff">then</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            None
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">else</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">let</SPAN> getMatchedGroupName (grps:GroupCollection) names = List.find (fun (name:<SPAN style="COLOR: #0000ff">string</SPAN>) -&gt; grps.[name].Length &gt; 0) names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">match</SPAN> combinedRegex.<SPAN style="COLOR: #0000ff">Match</SPAN>(str, pos) <SPAN style="COLOR: #0000ff">with</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | mt when mt.Success &amp;&amp; pos = mt.Index  -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> groupName = getMatchedGroupName mt.Groups patterns.names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> column = mt.Index - lineStart
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> nextPos = pos + mt.Length
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> (nextLine, nextLineStart) = <SPAN style="COLOR: #0000ff">if</SPAN> nextlineMap.Item groupName <SPAN style="COLOR: #0000ff">then</SPAN> (line + 1, nextPos) <SPAN style="COLOR: #0000ff">else</SPAN> (line,lineStart)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> token = <SPAN style="COLOR: #0000ff">if</SPAN> ignoreMap.Item groupName 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">then</SPAN> None 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">else</SPAN> Some {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        name = groupName; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        text = mt.Value; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        pos = pos; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        line = line; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        column = column; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    Some(token, (nextPos, nextLine, nextLineStart))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | otherwise -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> textAroundError = str.Substring(pos, min (pos + 5) str.Length)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    raise (ArgumentException (sprintf "<SPAN style="COLOR: #8b0000">Lexing error occured at line:%d and column:%d near the text:%s</SPAN>" line (pos - lineStart) textAroundError))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Seq.unfold tokenizeStep (0, 0, 0) |&gt; Seq.<SPAN style="COLOR: #0000ff">filter</SPAN> (fun x -&gt; x.IsSome) |&gt; Seq.map (fun x -&gt; x.Value)</PRE></PRE>
<P>Lastly, here are the unit tests written using <A href="http://xunit.codeplex.com/" mce_href="http://xunit.codeplex.com/">XUnit.Net</A>:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module LexerFacts
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Xunit
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open System.Linq
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> simpleDefs = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NextLine</SPAN>"           "<SPAN style="COLOR: #8b0000">/</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">IgnoredSymbol</SPAN>"        "<SPAN style="COLOR: #8b0000">=+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">String</SPAN>"                     "<SPAN style="COLOR: #8b0000">[a-zA-Z]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Number</SPAN>"                     "<SPAN style="COLOR: #8b0000">\d+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Name</SPAN>"                       "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_return_no_tokens_for_empty_string() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000"></SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_throw_exception_for_invalid_token() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">-</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ex = Assert.ThrowsDelegateWithReturn(fun () -&gt; upcast tokens.Count()) |&gt; Record.Exception
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.NotNull(ex)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.True(ex :? System.ArgumentException)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_ignore_symbols_defined_as_ignore_symbols() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">=========</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_get_token_with_correct_position_and_type() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one=2=two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_tokenize_string_with_alernating_numbers_and_strings() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">1</SPAN>",tokens.ElementAt(0).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">one</SPAN>",tokens.ElementAt(1).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">two</SPAN>",tokens.ElementAt(3).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_increment_line_with_newline_symbol() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one/2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(1,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_give_priority_to_lexer_definitions_defined_earlier() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">String</SPAN>",tokens.ElementAt(0).name)</PRE></PRE>
<P mce_keep="true">&nbsp;</P>
<P>I attached a zip (<A href="http://blogs.msdn.com/matt/attachment/9950348.ashx" mce_href="http://blogs.msdn.com/matt/attachment/9950348.ashx">Lexer.zip</A>) containing all the code mentioned above.</P><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9950348" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-09-95-03-48/Lexer.zip" length="2225" type="application/x-zip-compressed" />
		</item>
		<item>
		<title>Regex based Lexer with F#</title>
		<link>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-3/</link>
		<comments>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-3/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 14:52:00 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">/b/matt/archive/2010/01/19/regex-lexer-with-f.aspx</guid>
		<description><![CDATA[This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. open Lexer
let definitions = 
    lexerDefinitions {
        do! addNextlineDefinition "NEWLINE" @"(\n\r)&#124;\n&#124;\r"
        do!...]]></description>
			<content:encoded><![CDATA[<P>This lexer allows you to define your regular expression based rules in a very declarative way using F# computation expressions. </P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> definitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    lexerDefinitions {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NEWLINE</SPAN>" @"<SPAN style="COLOR: #8b0000">(\n\r)|\n|\r</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">WS</SPAN>"        @"<SPAN style="COLOR: #8b0000">\s</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">LET</SPAN>"             "<SPAN style="COLOR: #8b0000">let</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">ID</SPAN>"              "<SPAN style="COLOR: #8b0000">(?i)[a-z][a-z0-9]*</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">FLOAT</SPAN>"           @"<SPAN style="COLOR: #8b0000">[0-9]+\.[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">INT</SPAN>"             "<SPAN style="COLOR: #8b0000">[0-9]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">OPERATOR</SPAN>"      @"<SPAN style="COLOR: #8b0000">[+*=!/&amp;|&lt;&gt;\^\-]+</SPAN>"   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }</PRE></PRE>
<P>With those defined you can execute the lexer with:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> lex input = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">try</SPAN>    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN> y = Lexer.tokenize definitions input
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        printfn "<SPAN style="COLOR: #8b0000">%A</SPAN>" y
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">with</SPAN> e -&gt; printf "<SPAN style="COLOR: #8b0000">%s</SPAN>" e.Message
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">lex "<SPAN style="COLOR: #8b0000">let a = 5</SPAN>"</PRE></PRE>
<P>Which will result in:</P>
<BLOCKQUOTE>
<P align=left>seq [{name = "LET"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "let"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "ID"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "a"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 4; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "OPERATOR"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "="; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 6; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}; {name = "INT"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = "5"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = 8; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = 0;}]</P></BLOCKQUOTE>
<P align=left>The lexer’s code is structured in three parts.&nbsp; The first part is a state monad using the F# computation expressions.&nbsp; This enables the declarative approach (seen above) to setup your lexer rules.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module StateMonad
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type State&lt;'s,'a&gt; = State of ('s -&gt; ('a *'s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> runState (State f) = f
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type StateBuilder() = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Return(x) = State (fun s -&gt; (x,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Delay(f) = f() : State&lt;'s,'a&gt;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Zero() = State (fun s -&gt; ((),s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Bind(State p,rest) = State (fun s -&gt; <SPAN style="COLOR: #0000ff">let</SPAN> v,s2 = p s <SPAN style="COLOR: #0000ff">in</SPAN>  (runState (rest v)) s2)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.<SPAN style="COLOR: #0000ff">Get</SPAN> () = State (fun s -&gt; (s,s))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    member b.Put s = State (fun _ -&gt; ((),s))</PRE></PRE>
<P>The second part are the combinators that are used to define your lexer rules.&nbsp; There are three main combinators:&nbsp; <STRONG>AddDefinition</STRONG> which lets you define a name / regex pair, <STRONG>AddIgnoreDefinition </STRONG>which lets you define characters which the lexer should ignore and <STRONG>AddNextlineDefinition </STRONG>which lets you define what characters determine a new line.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type LexDefinitions = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  {regexes : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   names : <SPAN style="COLOR: #0000ff">string</SPAN> list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   nextlines : bool list;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   ignores : bool list; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> buildDefinition name pattern nextLine ignore =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">let</SPAN>! x = state.<SPAN style="COLOR: #0000ff">Get</SPAN>()
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! state.Put { regexes = x.regexes @  [sprintf @"<SPAN style="COLOR: #8b0000">(?&lt;%s&gt;%s)</SPAN>" name pattern];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        names = x.names @ [name]; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        nextlines  = x.nextlines @ [nextLine];
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                        ignores = x.ignores @ [ignore]}
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addDefinition name pattern = buildDefinition name pattern false false
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addIgnoreDefinition name pattern = buildDefinition name pattern false true
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> addNextlineDefinition name pattern = buildDefinition name pattern true true    </PRE></PRE>
<P>And the final part is the code that performs the tokenizing.&nbsp; It uses the Seq.unfold method to create the list of tokens.&nbsp; Unfold is a function which takes a single item and generates a list of new items from it.&nbsp; It is the opposite of Seq.fold which takes a list of items and turns it into a single item.&nbsp; The tokenize function used Seq.unfold to generate each token while keeping track of the current line number, position in that line and position in the input string.</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">type Token = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    { name : <SPAN style="COLOR: #0000ff">string</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      text: <SPAN style="COLOR: #0000ff">string</SPAN>; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      pos :<SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      column: <SPAN style="COLOR: #0000ff">int</SPAN>;
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">      line: <SPAN style="COLOR: #0000ff">int</SPAN> }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">   
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> createLexDefs pb =  (runState pb) {regexes = []; names = []; nextlines = []; ignores = []} |&gt; snd
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"> 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> tokenize lexerBuilder (str:<SPAN style="COLOR: #0000ff">string</SPAN>) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> patterns = createLexDefs lexerBuilder
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> combinedRegex =  Regex(List.fold (fun acc reg -&gt; acc + "<SPAN style="COLOR: #8b0000">|</SPAN>" + reg) (List.head patterns.regexes) (List.tail patterns.regexes))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> nextlineMap = List.zip patterns.names patterns.nextlines |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ignoreMap = List.zip patterns.names patterns.ignores |&gt; Map.ofList
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokenizeStep (pos,line,lineStart) = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">if</SPAN> pos &gt;= str.Length <SPAN style="COLOR: #0000ff">then</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            None
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">else</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">let</SPAN> getMatchedGroupName (grps:GroupCollection) names = List.find (fun (name:<SPAN style="COLOR: #0000ff">string</SPAN>) -&gt; grps.[name].Length &gt; 0) names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">            <SPAN style="COLOR: #0000ff">match</SPAN> combinedRegex.<SPAN style="COLOR: #0000ff">Match</SPAN>(str, pos) <SPAN style="COLOR: #0000ff">with</SPAN>
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | mt when mt.Success &amp;&amp; pos = mt.Index  -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> groupName = getMatchedGroupName mt.Groups patterns.names
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> column = mt.Index - lineStart
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> nextPos = pos + mt.Length
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> (nextLine, nextLineStart) = <SPAN style="COLOR: #0000ff">if</SPAN> nextlineMap.Item groupName <SPAN style="COLOR: #0000ff">then</SPAN> (line + 1, nextPos) <SPAN style="COLOR: #0000ff">else</SPAN> (line,lineStart)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> token = <SPAN style="COLOR: #0000ff">if</SPAN> ignoreMap.Item groupName 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">then</SPAN> None 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                <SPAN style="COLOR: #0000ff">else</SPAN> Some {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        name = groupName; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        text = mt.Value; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        pos = pos; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        line = line; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                                        column = column; }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    Some(token, (nextPos, nextLine, nextLineStart))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                | otherwise -&gt; 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    <SPAN style="COLOR: #0000ff">let</SPAN> textAroundError = str.Substring(pos, min (pos + 5) str.Length)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">                    raise (ArgumentException (sprintf "<SPAN style="COLOR: #8b0000">Lexing error occured at line:%d and column:%d near the text:%s</SPAN>" line (pos - lineStart) textAroundError))
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Seq.unfold tokenizeStep (0, 0, 0) |&gt; Seq.<SPAN style="COLOR: #0000ff">filter</SPAN> (fun x -&gt; x.IsSome) |&gt; Seq.map (fun x -&gt; x.Value)</PRE></PRE>
<P>Lastly, here are the unit tests written using <A href="http://xunit.codeplex.com/" mce_href="http://xunit.codeplex.com/">XUnit.Net</A>:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">module LexerFacts
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Xunit
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open Lexer
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">open System.Linq
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> simpleDefs = 
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    state {
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addNextlineDefinition "<SPAN style="COLOR: #8b0000">NextLine</SPAN>"           "<SPAN style="COLOR: #8b0000">/</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addIgnoreDefinition "<SPAN style="COLOR: #8b0000">IgnoredSymbol</SPAN>"        "<SPAN style="COLOR: #8b0000">=+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">String</SPAN>"                     "<SPAN style="COLOR: #8b0000">[a-zA-Z]+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Number</SPAN>"                     "<SPAN style="COLOR: #8b0000">\d+</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">        <SPAN style="COLOR: #0000ff">do</SPAN>! addDefinition "<SPAN style="COLOR: #8b0000">Name</SPAN>"                       "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    }
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_return_no_tokens_for_empty_string() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000"></SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_throw_exception_for_invalid_token() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">-</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> ex = Assert.ThrowsDelegateWithReturn(fun () -&gt; upcast tokens.Count()) |&gt; Record.Exception
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.NotNull(ex)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.True(ex :? System.ArgumentException)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_ignore_symbols_defined_as_ignore_symbols() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">=========</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0, tokens.Count())
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_get_token_with_correct_position_and_type() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one=2=two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_tokenize_string_with_alernating_numbers_and_strings() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">1</SPAN>",tokens.ElementAt(0).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">one</SPAN>",tokens.ElementAt(1).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">two</SPAN>",tokens.ElementAt(3).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_increment_line_with_newline_symbol() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">1one/2two</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">Number</SPAN>",tokens.ElementAt(2).name)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">2</SPAN>",tokens.ElementAt(2).text)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(5,tokens.ElementAt(2).pos)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(0,tokens.ElementAt(2).column)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal(1,tokens.ElementAt(2).line)
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">[&lt;Fact&gt;]
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px"><SPAN style="COLOR: #0000ff">let</SPAN> Will_give_priority_to_lexer_definitions_defined_earlier() =
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">  
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    <SPAN style="COLOR: #0000ff">let</SPAN> tokens = Lexer.tokenize simpleDefs "<SPAN style="COLOR: #8b0000">Matt</SPAN>"
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    
</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 11px">    Assert.Equal("<SPAN style="COLOR: #8b0000">String</SPAN>",tokens.ElementAt(0).name)</PRE></PRE>
<P mce_keep="true">&nbsp;</P>
<P>I attached a zip (<A href="http://blogs.msdn.com/matt/attachment/9950348.ashx" mce_href="http://blogs.msdn.com/matt/attachment/9950348.ashx">Lexer.zip</A>) containing all the code mentioned above.</P><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9950348" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2010/01/19/regex-based-lexer-with-f-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-09-95-03-48/Lexer.zip" length="2225" type="application/x-zip-compressed" />
		</item>
		<item>
		<title>A functional take on console program loop in F#</title>
		<link>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f/</link>
		<comments>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 07:51:19 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">http://blogs.msdn.com/matt/archive/2009/04/13/a-functional-take-on-console-program-loop-in-f.aspx</guid>
		<description><![CDATA[Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:  Enter input: someInput...]]></description>
			<content:encoded><![CDATA[<p>Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:</p>  <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 418px; padding-right: 5px; height: 133px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: someInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someOutput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: otherInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someoutPut</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: quit</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Thanks! Come again!</pre></pre>

<p>The code for this is in an imperative language is usually something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span>)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> {</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.Write(<span style="color: #006080">&quot;\nEnter input:&quot;</span>);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     var line = Console.ReadLine();</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">if</span>(line == <span style="color: #006080">&quot;quit&quot;</span>) <span style="color: #0000ff">break</span>;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     doSomething(line);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> }</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span> Console.WriteLine(<span style="color: #006080">&quot;Thanks! Come Again&quot;</span>);</pre>
  </div>
</div>

<p>&#160;</p>

<p>While reading some F# samples, I saw some code doing essentially the same thing which looked something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> <span style="color: #0000ff">let</span> mutable input = Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">while</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     <span style="color: #0000ff">do</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">if</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">then</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>         doSomething input</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>         Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>         input &lt;- Console.ReadLine()</pre>
  </div>
</div>

<p></p>

<p>&#160;</p>

<p>Now this just feels dirty! In a functional language explicit loop constructs like a while loop feel wrong.&#160; I different way of doing this which is more functional is to create an infinite list of actions.&#160; Where each action represents one iteration of any of the above loops. Then you just execute each action until some condition is met (like seeing the input “quit”).</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; height: 255px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">let</span> action = fun _ -&gt;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     Console.Write <span style="color: #006080">&quot;\nEnter input: &quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span> <span style="color: #0000ff">let</span> readlines = Seq.init_infinite (fun _ -&gt; action())</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span> <span style="color: #0000ff">let</span> run item = <span style="color: #0000ff">if</span> item = <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>                 <span style="color: #0000ff">then</span> Some(item) </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>                 <span style="color: #0000ff">else</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>                     parse item </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span>                     None</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  12:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  13:</span> Seq.first run readlines |&gt; ignore</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  14:</span> Console.WriteLine <span style="color: #006080">&quot;Thanks! Come Again&quot;</span></pre>
  </div>
</div>

<p>This code makes use of the Seq.init_infinite which create a infinite sequence and Seq.first which enumerates the sequence until the passed in function returns Some.</p><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9547889" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A functional take on console program loop in F#</title>
		<link>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-3/</link>
		<comments>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-3/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 07:51:19 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">/b/matt/archive/2009/04/13/a-functional-take-on-console-program-loop-in-f.aspx</guid>
		<description><![CDATA[Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:  Enter input: someInput...]]></description>
			<content:encoded><![CDATA[<p>Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:</p>  <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 418px; padding-right: 5px; height: 133px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: someInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someOutput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: otherInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someoutPut</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: quit</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Thanks! Come again!</pre></pre>

<p>The code for this is in an imperative language is usually something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span>)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> {</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.Write(<span style="color: #006080">&quot;\nEnter input:&quot;</span>);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     var line = Console.ReadLine();</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">if</span>(line == <span style="color: #006080">&quot;quit&quot;</span>) <span style="color: #0000ff">break</span>;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     doSomething(line);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> }</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span> Console.WriteLine(<span style="color: #006080">&quot;Thanks! Come Again&quot;</span>);</pre>
  </div>
</div>

<p>&#160;</p>

<p>While reading some F# samples, I saw some code doing essentially the same thing which looked something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> <span style="color: #0000ff">let</span> mutable input = Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">while</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     <span style="color: #0000ff">do</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">if</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">then</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>         doSomething input</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>         Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>         input &lt;- Console.ReadLine()</pre>
  </div>
</div>

<p></p>

<p>&#160;</p>

<p>Now this just feels dirty! In a functional language explicit loop constructs like a while loop feel wrong.&#160; I different way of doing this which is more functional is to create an infinite list of actions.&#160; Where each action represents one iteration of any of the above loops. Then you just execute each action until some condition is met (like seeing the input “quit”).</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; height: 255px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">let</span> action = fun _ -&gt;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     Console.Write <span style="color: #006080">&quot;\nEnter input: &quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span> <span style="color: #0000ff">let</span> readlines = Seq.init_infinite (fun _ -&gt; action())</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span> <span style="color: #0000ff">let</span> run item = <span style="color: #0000ff">if</span> item = <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>                 <span style="color: #0000ff">then</span> Some(item) </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>                 <span style="color: #0000ff">else</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>                     parse item </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span>                     None</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  12:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  13:</span> Seq.first run readlines |&gt; ignore</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  14:</span> Console.WriteLine <span style="color: #006080">&quot;Thanks! Come Again&quot;</span></pre>
  </div>
</div>

<p>This code makes use of the Seq.init_infinite which create a infinite sequence and Seq.first which enumerates the sequence until the passed in function returns Some.</p><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9547889" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A functional take on console program loop in F#</title>
		<link>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-2/</link>
		<comments>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-2/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 07:51:19 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">/b/matt/archive/2009/04/13/a-functional-take-on-console-program-loop-in-f.aspx</guid>
		<description><![CDATA[Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:  Enter input: someInput...]]></description>
			<content:encoded><![CDATA[<p>Often when learning a new technology I start with a simple console application in which the program is run in a loop it continues to prompt you for more input until you give some command like quit or exit or whatever you choose:</p>  <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 418px; padding-right: 5px; height: 133px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: someInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someOutput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: otherInput</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">someoutPut</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Enter input: quit</pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 11px">Thanks! Come again!</pre></pre>

<p>The code for this is in an imperative language is usually something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span>)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> {</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.Write(<span style="color: #006080">&quot;\nEnter input:&quot;</span>);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     var line = Console.ReadLine();</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">if</span>(line == <span style="color: #006080">&quot;quit&quot;</span>) <span style="color: #0000ff">break</span>;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     doSomething(line);</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> }</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span> Console.WriteLine(<span style="color: #006080">&quot;Thanks! Come Again&quot;</span>);</pre>
  </div>
</div>

<p>&#160;</p>

<p>While reading some F# samples, I saw some code doing essentially the same thing which looked something like:</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> <span style="color: #0000ff">let</span> mutable input = Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">while</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     <span style="color: #0000ff">do</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">if</span> input &lt;&gt; <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">then</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>         doSomething input</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>         Console.Write <span style="color: #006080">&quot;\nEnter input:&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>         input &lt;- Console.ReadLine()</pre>
  </div>
</div>

<p></p>

<p>&#160;</p>

<p>Now this just feels dirty! In a functional language explicit loop constructs like a while loop feel wrong.&#160; I different way of doing this which is more functional is to create an infinite list of actions.&#160; Where each action represents one iteration of any of the above loops. Then you just execute each action until some condition is met (like seeing the input “quit”).</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; height: 255px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">let</span> action = fun _ -&gt;</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     Console.Write <span style="color: #006080">&quot;\nEnter input: &quot;</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     Console.ReadLine()</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span> <span style="color: #0000ff">let</span> readlines = Seq.init_infinite (fun _ -&gt; action())</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span> <span style="color: #0000ff">let</span> run item = <span style="color: #0000ff">if</span> item = <span style="color: #006080">&quot;quit&quot;</span> </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>                 <span style="color: #0000ff">then</span> Some(item) </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>                 <span style="color: #0000ff">else</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>                     parse item </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span>                     None</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  12:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  13:</span> Seq.first run readlines |&gt; ignore</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  14:</span> Console.WriteLine <span style="color: #006080">&quot;Thanks! Come Again&quot;</span></pre>
  </div>
</div>

<p>This code makes use of the Seq.init_infinite which create a infinite sequence and Seq.first which enumerates the sequence until the passed in function returns Some.</p><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9547889" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2009/04/14/a-functional-take-on-console-program-loop-in-f-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parameterized State Transformer Monad in F#?</title>
		<link>http://matthewmanela.com/2008/11/05/parameterized-state-transformer-monad-in-f-2/</link>
		<comments>http://matthewmanela.com/2008/11/05/parameterized-state-transformer-monad-in-f-2/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 08:30:29 +0000</pubDate>
		<dc:creator>MattManela</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">/b/matt/archive/2008/11/04/parameterized-state-transformer-monad-in-f.aspx</guid>
		<description><![CDATA[I have have been playing around with F# and I decided to create a state monad.&#160; This worked out really well since I was able to leverage the F# computation expressions.&#160; I then decided to try to extend this and make it more general by creatin...]]></description>
			<content:encoded><![CDATA[<p>I have have been playing around with F# and I decided to create a state monad.&nbsp; This worked out really well since I was able to leverage the <a href="http://blogs.msdn.com/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow-syntax.aspx" >F# computation expressions</a>.&nbsp; I then decided to try to extend this and make it more general by creating a parameterized state transformer monad.&nbsp; This is a state monad which encapsulates another monad.&nbsp; What this allow you to do is turn any computation into a statefull one.</p> <p>&nbsp;</p> <p>This concept exists in Haskell which you can see <a href="http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-State.html#3" >here</a>. However, my attempts at replicating this in F# failed.&nbsp; Unlike in Haskell, the computation expressions in F# don't share a common interface (or type class).&nbsp; This prevents a computation from being able to generically take another computation as a parameter.&nbsp; The reason is that an operation on the parameterized state transformer monad such as bind will result in a bind called on its encapsulated monad.&nbsp; But since there is no interface for computations there is no bind method to call.&nbsp; </p> <p>I attempted to fix this by creating my own monad interface but this didn't work:</p> <div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"> <div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   1:</span> type Monad =</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   2:</span>     abstract Bind : 'm * ('a -<span style="color: #0000ff">&gt;</span> 'm) -<span style="color: #0000ff">&gt;</span> 'm</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   3:</span>     abstract Delay : (unit -<span style="color: #0000ff">&gt;</span>'m) -<span style="color: #0000ff">&gt;</span> 'm</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   4:</span>     abstract Let : 'a * ('a -<span style="color: #0000ff">&gt;</span> 'm) -<span style="color: #0000ff">&gt;</span> 'm</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   5:</span>     abstract Return : 'a -<span style="color: #0000ff">&gt;</span> 'm</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   6:</span>     abstract Zero : unit -<span style="color: #0000ff">&gt;</span> 'm</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   7:</span>     abstract Combine : 'm -<span style="color: #0000ff">&gt;</span> 'm2 -<span style="color: #0000ff">&gt;</span> 'm3</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   8:</span>     abstract Run : (unit -<span style="color: #0000ff">&gt;</span>'m) -<span style="color: #0000ff">&gt;</span> 'm</pre></div></div>
<p>&nbsp;</p>
<p>After playing with that and failing I ended up with a less than ideal solution.&nbsp; Given a Maybe monad like below:</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   1:</span> // Maybe Monad    </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   2:</span> type MaybeBuilder() =</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   3:</span>     member b.Return(x) = Some x</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   4:</span>     member b.Run(f) = f()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   5:</span>     member b.Delay(f) = f</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   6:</span>     member b.Let(p,rest) = rest p</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   7:</span>     member b.Zero () = None</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   8:</span>     member b.Combine(m1,dm2) = match m1 with</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   9:</span>                                  | None -<span style="color: #0000ff">&gt;</span> dm2()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  10:</span>                                  | x -<span style="color: #0000ff">&gt;</span> x</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  11:</span>&nbsp; </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  12:</span>     member b.Bind(p,rest) = match p with </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  13:</span>                             | None -<span style="color: #0000ff">&gt;</span> None</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  14:</span>                             | Some r -<span style="color: #0000ff">&gt;</span> rest r</pre></div></div>
<p>&nbsp;</p>
<p>I created a state transformer monad which take an argument of type m:MaybeBuilder</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   1:</span> type StateMBuilder(m:MaybeBuilder) = </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   2:</span>     member b.Return(x) = fun s -<span style="color: #0000ff">&gt;</span> m.Return (x,s)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   3:</span>     member b.Run(f) = fun inp -<span style="color: #0000ff">&gt;</span> (f inp)()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   4:</span>     member b.Delay(f) = fun inp -<span style="color: #0000ff">&gt;</span> fun () -<span style="color: #0000ff">&gt;</span> f() inp</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   5:</span>     member b.Let(p,rest) = rest p</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   6:</span>     member b.Zero () = fun s -<span style="color: #0000ff">&gt;</span> m.Zero()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   7:</span>     member b.Bind(p,rest) = fun s -<span style="color: #0000ff">&gt;</span> m.Bind(p s,fun (v,s2) -<span style="color: #0000ff">&gt;</span> rest v s2)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   8:</span>     member b.Combine(p1,dp2) = fun s -<span style="color: #0000ff">&gt;</span> m.Combine(p1 s, dp2 s)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   9:</span>&nbsp; </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  10:</span>     // State specific functions</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  11:</span>     member b.Update f = fun s -<span style="color: #0000ff">&gt;</span> try m.Return (s, f s) with e -<span style="color: #0000ff">&gt;</span> m.Zero()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  12:</span>     member b.Read () = b.Update id</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">  13:</span>     member b.Set t = b.Update (fun _ -<span style="color: #0000ff">&gt;</span> t)</pre></div></div>
<p>&nbsp;</p>
<p>Now although this type is technically parameterized ;) it isn't really the idea since its not generic, it has to be a MaybeBuilder.&nbsp; To use this with a different monad I would need to change m:MaybeBuild to m:SomeOtherMonad.&nbsp; </p>
<p>I am still going to play with this but this is as far as I have gotten.</p>
<p>After all of that here is how you create a state transformer monad parameterized over the maybe monad:</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   1:</span> let maybe = MaybeBuilder()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #606060">   2:</span> let state = StateMBuilder(maybe)</pre></div></div>
<p>&nbsp;</p>
<p>If anyone has an idea how I can make this work I would love to hear it.</p><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9043440" width="1" height="1">]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2008/11/05/parameterized-state-transformer-monad-in-f-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parameterized State Transformer Monad in F#?</title>
		<link>http://matthewmanela.com/2008/03/11/parameterized-state-transformer-monad-in-f/</link>
		<comments>http://matthewmanela.com/2008/03/11/parameterized-state-transformer-monad-in-f/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 22:28:14 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">http://matthewmanela.com/?p=317</guid>
		<description><![CDATA[I have have been playing around with F# and I decided to create a state monad.&#160; This worked out really well since I was able to leverage the F# computation expressions.&#160; I then decided to try to extend this and make it more general by creating a parameterized state transformer monad.&#160; This is a state [...]]]></description>
			<content:encoded><![CDATA[<p><P>I have have been playing around with F# and I decided to create a state monad.&nbsp; This worked out really well since I was able to leverage the <A href="http://blogs.msdn.com/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow-syntax.aspx" target=_blank mce_href="http://blogs.msdn.com/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow-syntax.aspx">F# computation expressions</A>.&nbsp; I then decided to try to extend this and make it more general by creating a parameterized state transformer monad.&nbsp; This is a state monad which encapsulates another monad.&nbsp; What this allow you to do is turn any computation into a statefull one.</P></p>

<p><P mce_keep="true">&nbsp;</P></p>

<p><P>This concept exists in Haskell which you can see <A href="http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-State.html#3" target=_blank mce_href="http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-State.html#3">here</A>. However, my attempts at replicating this in F# failed.&nbsp; Unlike in Haskell, the computation expressions in F# don&#8217;t share a common interface (or type class).&nbsp; This prevents a computation from being able to generically take another computation as a parameter.&nbsp; The reason is that an operation on the parameterized state transformer monad such as bind will result in a bind called on its encapsulated monad.&nbsp; But since there is no interface for computations there is no bind method to call.&nbsp; </P></p>

<p><P>I attempted to fix this by creating my own monad interface but this didn&#8217;t work:</P></p>

<p><DIV style="BORDER-BOTTOM: gray 1px solid; BORDER-LEFT: gray 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: gray 1px solid; CURSOR: text; BORDER-RIGHT: gray 1px solid; PADDING-TOP: 4px">
<DIV style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px">
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   1:</SPAN> type Monad =</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   2:</SPAN>     abstract Bind : &#8216;m * (&#8216;a -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m) -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   3:</SPAN>     abstract Delay : (unit -<SPAN style="COLOR: #0000ff">&gt;</SPAN>&#8216;m) -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   4:</SPAN>     abstract Let : &#8216;a * (&#8216;a -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m) -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   5:</SPAN>     abstract Return : &#8216;a -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   6:</SPAN>     abstract Zero : unit -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   7:</SPAN>     abstract Combine : &#8216;m -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m2 -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m3</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   8:</SPAN>     abstract Run : (unit -<SPAN style="COLOR: #0000ff">&gt;</SPAN>&#8216;m) -<SPAN style="COLOR: #0000ff">&gt;</SPAN> &#8216;m</PRE></DIV></DIV>
<P mce_keep="true">&nbsp;</P></p>

<p><P>After playing with that and failing I ended up with a less than ideal solution.&nbsp; Given a Maybe monad like below:</P></p>

<p><DIV style="BORDER-BOTTOM: gray 1px solid; BORDER-LEFT: gray 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: gray 1px solid; CURSOR: text; BORDER-RIGHT: gray 1px solid; PADDING-TOP: 4px">
<DIV style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px">
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   1:</SPAN> // Maybe Monad    </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   2:</SPAN> type MaybeBuilder() =</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   3:</SPAN>     member b.Return(x) = Some x</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   4:</SPAN>     member b.Run(f) = f()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   5:</SPAN>     member b.Delay(f) = f</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   6:</SPAN>     member b.Let(p,rest) = rest p</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   7:</SPAN>     member b.Zero () = None</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   8:</SPAN>     member b.Combine(m1,dm2) = match m1 with</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   9:</SPAN>                                  | None -<SPAN style="COLOR: #0000ff">&gt;</SPAN> dm2()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  10:</SPAN>                                  | x -<SPAN style="COLOR: #0000ff">&gt;</SPAN> x</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  11:</SPAN>&nbsp; </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  12:</SPAN>     member b.Bind(p,rest) = match p with </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  13:</SPAN>                             | None -<SPAN style="COLOR: #0000ff">&gt;</SPAN> None</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  14:</SPAN>                             | Some r -<SPAN style="COLOR: #0000ff">&gt;</SPAN> rest r</PRE></DIV></DIV>
<P mce_keep="true">&nbsp;</P></p>

<p><P>I created a state transformer monad which take an argument of type m:MaybeBuilder</P></p>

<p><DIV style="BORDER-BOTTOM: gray 1px solid; BORDER-LEFT: gray 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: gray 1px solid; CURSOR: text; BORDER-RIGHT: gray 1px solid; PADDING-TOP: 4px">
<DIV style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px">
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   1:</SPAN> type StateMBuilder(m:MaybeBuilder) = </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   2:</SPAN>     member b.Return(x) = fun s -<SPAN style="COLOR: #0000ff">&gt;</SPAN> m.Return (x,s)</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   3:</SPAN>     member b.Run(f) = fun inp -<SPAN style="COLOR: #0000ff">&gt;</SPAN> (f inp)()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   4:</SPAN>     member b.Delay(f) = fun inp -<SPAN style="COLOR: #0000ff">&gt;</SPAN> fun () -<SPAN style="COLOR: #0000ff">&gt;</SPAN> f() inp</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   5:</SPAN>     member b.Let(p,rest) = rest p</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   6:</SPAN>     member b.Zero () = fun s -<SPAN style="COLOR: #0000ff">&gt;</SPAN> m.Zero()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   7:</SPAN>     member b.Bind(p,rest) = fun s -<SPAN style="COLOR: #0000ff">&gt;</SPAN> m.Bind(p s,fun (v,s2) -<SPAN style="COLOR: #0000ff">&gt;</SPAN> rest v s2)</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   8:</SPAN>     member b.Combine(p1,dp2) = fun s -<SPAN style="COLOR: #0000ff">&gt;</SPAN> m.Combine(p1 s, dp2 s)</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   9:</SPAN>&nbsp; </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  10:</SPAN>     // State specific functions</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  11:</SPAN>     member b.Update f = fun s -<SPAN style="COLOR: #0000ff">&gt;</SPAN> try m.Return (s, f s) with e -<SPAN style="COLOR: #0000ff">&gt;</SPAN> m.Zero()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  12:</SPAN>     member b.Read () = b.Update id</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  13:</SPAN>     member b.Set t = b.Update (fun _ -<SPAN style="COLOR: #0000ff">&gt;</SPAN> t)</PRE></DIV></DIV>
<P mce_keep="true">&nbsp;</P></p>

<p><P>Now although this type is technically parameterized <img src='http://matthewmanela.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  it isn&#8217;t really the idea since its not generic, it has to be a MaybeBuilder.&nbsp; To use this with a different monad I would need to change m:MaybeBuild to m:SomeOtherMonad.&nbsp; </P></p>

<p><P>I am still going to play with this but this is as far as I have gotten.</P></p>

<p><P>After all of that here is how you create a state transformer monad parameterized over the maybe monad:</P></p>

<p><DIV style="BORDER-BOTTOM: gray 1px solid; BORDER-LEFT: gray 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: gray 1px solid; CURSOR: text; BORDER-RIGHT: gray 1px solid; PADDING-TOP: 4px">
<DIV style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px">
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   1:</SPAN> let maybe = MaybeBuilder()</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   2:</SPAN> let state = StateMBuilder(maybe)</PRE></DIV></DIV>
<P mce_keep="true">&nbsp;</P></p>

<p><P>If anyone has an idea how I can make this work I would love to hear it.</P></p>
]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2008/03/11/parameterized-state-transformer-monad-in-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I started playing with F#&#8230;</title>
		<link>http://matthewmanela.com/2008/03/11/i-started-playing-with-f/</link>
		<comments>http://matthewmanela.com/2008/03/11/i-started-playing-with-f/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 22:26:13 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">http://matthewmanela.com/?p=305</guid>
		<description><![CDATA[I decided to do some Project Euler problems using F#.&#160; So here is my first one, Problem # 31.&#160; Nothing in this solution really shows off anything special about F# but you have to start somewhere 1: #light 2:&#160; 3: let rec combos amt (denoms:int list) = 4: if amt = 0 then 1 5: [...]]]></description>
			<content:encoded><![CDATA[<p><P>I decided to do some <A href="http://projecteuler.net/" mce_href="http://projecteuler.net">Project Euler</A> problems using F#.&nbsp; </P></p>

<p><P>So here is my first one, Problem # 31.&nbsp; Nothing in this solution really shows off anything special about F# but you have to start somewhere <img src='http://matthewmanela.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </P></p>

<p><DIV style="BORDER-BOTTOM: gray 1px solid; BORDER-LEFT: gray 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: gray 1px solid; CURSOR: text; BORDER-RIGHT: gray 1px solid; PADDING-TOP: 4px">
<DIV style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px">
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   1:</SPAN> #light</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   2:</SPAN>&nbsp; </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   3:</SPAN> let rec combos amt (denoms:<SPAN style="COLOR: #0000ff">int</SPAN> list) = </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   4:</SPAN>     <SPAN style="COLOR: #0000ff">if</SPAN> amt = 0 then 1</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   5:</SPAN>     elif denoms.IsEmpty || amt &lt; 0 then 0</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   6:</SPAN>     <SPAN style="COLOR: #0000ff">else</SPAN> </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   7:</SPAN>         combos (amt &#8211; denoms.Head) denoms + </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   8:</SPAN>         combos amt denoms.Tail</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">   9:</SPAN>     </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  10:</SPAN>     </PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  11:</SPAN> printf <SPAN style="COLOR: #006080">&#8220;\n\nThe Anwer is: %i \n&#8221;</SPAN> (combos 200 [200;100;50;20;10;5;2;1])</PRE>
<PRE style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060">  12:</SPAN>         </PRE></DIV></DIV></p>
]]></content:encoded>
			<wfw:commentRss>http://matthewmanela.com/2008/03/11/i-started-playing-with-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
