Thoughts and CodeLogic, art, coding...https://www.dotnetzone.gr:443/cs/blogs/palladin/atom.aspxCommunity Server2009-09-13T22:44:00ZFP Hacker Wantedhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2011/09/01/fp-hacker-wanted.aspx2011-09-02T03:44:00Z2011-09-02T03:44:00Z<div>H ομάδα μου και εγώ προσωπικά αναζητούμε F# hacker. Για περισσότερες πληροφορίες στείλτε μου PM.</div><div><br></div><div>"Είμαστε μια μικρή ομάδα έμπειρων F# προγραμματιστών και αναζητούμε νεαρό ταλαντούχο hacker</div><div> για να δουλέψει μαζί μας σε ένα πολύ ενδιαφέρον και φιλόδοξο F# based cloud programming framework-runtime (<a href="http://www.m-brace.net">M-Brace</a>). </div><div>Αν και οι γνώσεις γύρω από F# και .Net δεν είναι απαραίτητες, απαιτείται τουλάχιστον καλή γνώση και εμπειρία σε κάποια functional γλώσσα </div><div>(Lisp family, ML family, Haskell, Erlang, FP Scala) καθώς και πάθος-όρεξη για applied functional programming. </div><div>Για περισσότερες πληροφορίες και για αποστολή βιογραφικών nessos@nessos.gr"</div><div><br></div><div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=67008" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxF# in the Enterprisehttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2011/03/03/f-in-the-enterprise.aspx2011-03-04T01:37:00Z2011-03-04T01:37:00Z<div>Αργά αλλα σταθερά η F# δείχνει την δύναμη της και εδραιώνεται στις συνειδήσεις των .Net προγραμματιστών.</div><div>Μετά και την ανακοίνωση του Async support στις vNext (C#, Vb) είναι ξεκάθαρο ότι η F# επηρεάζει και ξεχωρίζει.</div><div>Στο παρακάτω link όσοι ενδιαφέρονται μπορούν να δουν και το enterprise πρόσωπο της F#.</div><div><br></div><div><a href="http://msdn.microsoft.com/en-us/fsharp/gg634701">http://msdn.microsoft.com/en-us/fsharp/gg634701</a></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=63951" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxLazy but Fasthttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2011/01/06/lazy-but-fast.aspx2011-01-07T02:10:00Z2011-01-07T02:10:00Z<div>Πολλές φορες έχω κάποιο αναδρομικό αλγόριθμο (p.x traversal ενός tree) και θέλω να τον εκτελέσω lazy.</div><div> </div><div>Δυστυχώς και σε F# (seq) και σε C# (iterators), οι αλγόριθμοι καταλήγουν σε quadratic time και πολλές φορες σε stack-overflows.</div><div> </div><div>Κουρασμένος από αυτή την κατάσταση, κατέληξα στο κάτωθι.</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">open System.Collections
open System.Collections.Generic
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// LazyList dataType + Monoid Structure</span>
type LazyList<'T> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Empty
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Cons of 'T <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> (unit -> LazyList<'T>)
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Delay of (unit -> LazyList<'T>)
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Combine of LazyList<'T> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> LazyList<'T> with
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">interface</span> IEnumerable<'T> with
member self.GetEnumerator() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// tail-recursive enumeration </span>
let rec toSeq stack <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
match stack with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> [] -> Seq.empty
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> head :: tail ->
match head with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Empty -> toSeq tail
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Cons (value, rest) -> seq { yield value; yield! toSeq <| rest () :: tail }
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Delay f -> toSeq <| f () :: tail
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Combine (first, second) -> toSeq <| first :: second :: tail
(toSeq [self]).GetEnumerator()
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">interface</span> IEnumerable with
member self.GetEnumerator() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> (self :> IEnumerable<'T>).GetEnumerator() :> _
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// Monoid Comprehension</span>
type LazyListBuilder() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
member self.Yield value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Cons (value, fun () -> Empty)
member self.YieldFrom value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> value
member self.Combine(first, second) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Combine (first, second)
member self.Delay f <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Delay f
member self.Zero() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Empty
let lazyList <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> LazyListBuilder()
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// Example</span>
#time
type Tree<'T> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Empty <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Branch of 'T <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> Tree<'T> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> Tree<'T>
let rec createBalancedTree n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span> n <= 0 then Empty
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">else</span> Branch (n, createBalancedTree (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> 1), createBalancedTree (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> 1))
let rec createLeftSpinedTree n acc <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span> n <= 0 then acc
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">else</span> createLeftSpinedTree (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> 1) (Branch (n, acc, Empty))
let tree <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> createBalancedTree 20
let leftSpinedTree <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> createLeftSpinedTree 100000 Empty
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// Seq test</span>
let rec flattenToSeq tree <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
match tree with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Empty -> Seq.empty
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Branch (value, left, right) ->
seq { yield value; yield! flattenToSeq left; yield! flattenToSeq right }
tree
|> flattenToSeq
|> Seq.length
leftSpinedTree
|> flattenToSeq
|> Seq.length
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// LazyList test</span>
let rec flattenToLazyList tree <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
match tree with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Empty -> LazyList.Empty
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Branch (value, left, right) ->
lazyList { yield value; yield! flattenToLazyList left; yield! flattenToLazyList right }
tree
|> flattenToLazyList
|> Seq.length
leftSpinedTree
|> flattenToLazyList
|> Seq.length </span></pre><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=62141" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspx'M'agic & LINQ - IT PRO DEV CONNECTIONShttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/12/10/m-agic-amp-linq-it-pro-dev-connections.aspx2010-12-11T01:44:00Z2010-12-11T01:44:00Z<DIV>Αν και καθυστερημένα... θα ήθελα να ευχαριστήσω <FONT class=Apple-style-span size=2>όλους τους φίλους για την παρουσία τους και τα πολύ καλά τους λόγια.</FONT></DIV>
<DIV><BR></DIV>
<DIV>Αν και η παρουσίαση ήταν κυρίως βασισμένη σε live <FONT class=Apple-style-span size=2>hacking... </FONT></DIV>
<DIV><FONT class=Apple-style-span size=2>προσπάθησα να σπάσω σε βήματα το refactoring για όποιον θέλει να μελετήσει τον κώδικα.</FONT></DIV><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=61493" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxHughes's list in F#https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/11/13/hughes-s-list-in-f.aspx2010-11-14T04:24:00Z2010-11-14T04:24:00Z<div>Ορίζοντας τις Combine και Zero σε ένα Computation expression μπορούμε <span class="Apple-style-span" style="font-size:13.1944px;">να έχουμε Monoid comprehensions.</span></div><div><span class="Apple-style-span" style="font-size:13.1944px;">Πρόσφατα παρατήρησα ότι το Monadic Append στα γνωστά (Array, List, Seq) είναι σχετικά αργό.</span></div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">#time
[ <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">for</span> i <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> {1..1000000} <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>
yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 2; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 3; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 4; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 5 ]
[<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">for</span> i <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> {1..1000000} <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>
yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 2; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 3; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 4; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 5 <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span>]
seq { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">for</span> i <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> {1..1000000} <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>
yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 2; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 3; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 4; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 5 } |> Seq.iter ignore</span></pre><br></div><div><br></div><div>Μια τεχνική για να έχουμε γρήγορο list append είναι να αξιοποιήσουμε <span class="Apple-style-span" style="font-size:13.1944px;">μια παλαιά ιδέα από έναν <a href="http://www.chalmers.se/cse/EN/people/hughes-john">guru</a>.</span></div><div><span class="Apple-style-span" style="font-size:13.1944px;"><br></span></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">type FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> 'a list -> 'a list
type FuncListBuilder() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
member self.Combine (first : FuncList<'a>, second : FuncList<'a>) : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> (first << second)
member self.Zero() : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> id
member self.Yield (value : 'a) : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> fun tail -> value :: tail
member self.YieldFrom (value : FuncList<'a>) : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> value
member self.For (list : FuncList<'a>, f : 'a -> FuncList<'b>) : FuncList<'b> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
fun tail -> [] |> list |> List.map f |> List.fold (fun acc value -> self.Combine(acc, value)) (self.Zero()) <| tail
member self.Delay ( f : unit -> FuncList<'a>) : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f ()
let funcList <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> FuncListBuilder()
let toFuncList (list : 'a list) : FuncList<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> list |> List.fold (fun acc value -> funcList { yield! acc; yield value }) id
[] |> funcList { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">for</span> i <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> toFuncList [1..1000000] <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>
yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 2; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 3; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 4; yield i <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 5 }</span></pre><br></div><div>Για περισσότερες πληροφορίες: <span class="Apple-style-span" style="font-family:arial, sans-serif;font-size:15.2778px;border-collapse:collapse;"><a href="http://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/lists.pdf" target="_blank">http://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/lists.pdf</a></span></div><div><br></div><div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=60861" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxLooking for Hackerhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/10/25/looking-for-hacker.aspx2010-10-25T21:50:00Z2010-10-25T21:50:00Z<p class="MsoNormal">H ομάδα μου και εγώ προσωπικά αναζητούμε F# hacker. Για περισσότερες πληροφορίες στείλτε μου PM.</p><p class="MsoNormal">"Είμαστε μια μικρή ομάδα έμπειρων F# προγραμματιστών και
αναζητούμε νεαρό ταλαντούχο hacker για να δουλέψει μαζί μας σε ένα πολύ
ενδιαφέρον και φιλόδοξο F# project. Αν και οι γνώσεις γύρω από F# και .Net δεν
είναι απαραίτητες, απαιτείται τουλάχιστον σχετική εμπειρία σε κάποια functional
γλώσσα (FP C#, FP Javascript, Lisp family, ML family, Haskell, Erlang) καθώς
και όρεξη και πάθος για applied functional programming.<span class="Apple-style-span" style="font-family:'Segoe UI', sans-serif;font-size:13.3333px;"> </span></p>
<p class="MsoNormal">Για περισσότερες πληροφορίες και για αποστολή βιογραφικών <span style="mso-ansi-language:EN-US;">nessos</span>@<span style="mso-ansi-language:EN-US;">nessos</span>.<span style="mso-ansi-language:EN-US;">gr"</span><span></span></p><p class="MsoNormal"><span style="mso-ansi-language:EN-US;"><br></span></p><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=60673" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxSteps in Scalahttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/10/13/steps-in-scala.aspx2010-10-13T07:15:00Z2010-10-13T07:15:00Z<div>Θα ήθελα να δώσω πολλά μπράβο στους συγγραφείς του<a href="http://www.cambridge.org/uk/catalogue/catalogue.asp?isbn=9780521747585"> Steps Scala</a> (Λοβέρδος, Συρόπουλος) <span class="Apple-style-span" style="font-size:13.1944px;">για το θεωρητικό content που συμπεριέλαβαν.</span></div><div><br></div><div>Ιδιαίτερη μνεία πρέπει να γίνει για τo κεφαλαιο "Higher Order Polymorphism", <span class="Apple-style-span" style="font-size:13.1944px;">που ασχολείται με τις ιδέες</span></div><div>του κλασικού πλέον <a href="http://research.microsoft.com/en-us/um/people/emeijer/Papers/fpca91.pdf">Banana paper</a>.</div><div><br></div><div>Έχοντας διαβάσει σχεδόν όλα τα βιβλία που έχουν βγει για Scala, μπορώ να <span class="Apple-style-span" style="font-size:13.1944px;">πω με σιγουριά ότι το συγκεκριμένο βιβλίο ξεχωρίζει.</span></div><div><span class="Apple-style-span" style="font-size:13.1944px;"><br></span></div><div><img width="150" height="200" src="http://www.scala-lang.org/sites/default/files/book_icons/steps-v2.gif"></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=60564" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxMonadic Retryhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/10/10/monadic-retry.aspx2010-10-11T01:41:00Z2010-10-11T01:41:00Z<div>Πολλές φορες έχουμε σενάρια που θα θέλαμε να εφαρμοσουμε συγκεκριμενα retry policies σε error prone computations.</div><div>Τα σενάρια αυτά εμφανίζονται αρκετά συχνά και κυρίως σε cloud computations.</div><div>Στο Azure για παράδειγμα, υπάρχουν και συγκεκριμένα APIs που παίζουν με Retry Policies.</div><div><br></div><div>Το παρακάτω monad είναι μια έμπνευση που είχα στο να κάνω combine το</div><div>reader monad (για το propagation του policy) μαζί με το exception monad έτσι ώστε να δομήσω ένα retry monad.</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">open System
open System.Threading
type ShouldRetry <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> ShouldRetry of (RetryCount <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> LastException -> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">bool</span> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> RetryDelay)
and RetryCount <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span>
and LastException <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> exn
and RetryDelay <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> TimeSpan
type RetryPolicy <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> RetryPolicy of ShouldRetry
type RetryPolicies() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> member NoRetry () : RetryPolicy <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
RetryPolicy( ShouldRetry (fun (retryCount, _) -> (retryCount < 1, TimeSpan.Zero)) )
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> member Retry (currentRetryCount : <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span> , intervalBewteenRetries : RetryDelay) : RetryPolicy <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
RetryPolicy( ShouldRetry (fun (retryCount, _) -> (currentRetryCount < retryCount, intervalBewteenRetries)))
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> member Retry (currentRetryCount : <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span>) : RetryPolicy <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
RetryPolicies.Retry(currentRetryCount, TimeSpan.Zero)
type RetryResult<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> RetrySuccess of 'a
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> RetryFailure of exn
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// Reader + Exception Monad DataType</span>
type Retry<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Retry of (RetryPolicy -> RetryResult<'a>)
type RetryBuilder() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
member self.Return (value : 'a) : Retry<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Retry (fun retryPolicy -> RetrySuccess value)
member self.Bind (retry : Retry<'a>, bindFunc : 'a -> Retry<'b>) : Retry<'b> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
Retry (fun retryPolicy ->
let (Retry retryFunc) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retry
match retryFunc retryPolicy with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> RetrySuccess value ->
let (Retry retryFunc') <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> bindFunc value
retryFunc' retryPolicy
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> RetryFailure exn -> RetryFailure exn )
member self.Delay (f : unit -> Retry<'a>) : Retry<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
Retry (fun retryPolicy ->
let mutable resultCell : option<RetryResult<'a>> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> None
let mutable lastExceptionCell : exn <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">null</span>
let (RetryPolicy(ShouldRetry shouldRetry)) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retryPolicy
let mutable canRetryCell : <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">bool</span> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>
let mutable currentRetryCountCell : <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> 0
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">while</span> canRetryCell <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">try</span>
let (Retry retryFunc) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f ()
let result <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retryFunc retryPolicy
resultCell <- Some result
canRetryCell <- <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>
with e ->
lastExceptionCell <- e
currentRetryCountCell <- 1 <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">+</span> currentRetryCountCell
match shouldRetry(currentRetryCountCell, lastExceptionCell) with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> (<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>, retryDelay) ->
canRetryCell <- <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>
Thread.Sleep(retryDelay)
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> (<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>, _) -> canRetryCell <- <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>
match resultCell with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Some result -> result
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> None -> RetryFailure lastExceptionCell )
[<AutoOpen>]
module Retry <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
let retry <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> RetryBuilder()
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// override default policy</span>
let retryWithPolicy (retryPolicy : RetryPolicy) (retry : Retry<'a>) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
Retry (fun _ -> let (Retry retryFunc) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retry <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> retryFunc retryPolicy)
let run (retry : Retry<'a>) (retryPolicy : RetryPolicy) : RetryResult<'a> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
let (Retry retryFunc) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retry
retryFunc retryPolicy
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// DivByzero example</span>
let rnd <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> System.Random()
let example <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
retry {
let! a <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retry { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> 1 <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">/</span> rnd.Next(0, 2) }
let! b <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retry { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> 2 <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">/</span> rnd.Next(0, 2) }
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// override default policy</span>
let! c <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> retryWithPolicy (RetryPolicies.NoRetry()) (retry { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> 3 <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">/</span> rnd.Next(0, 2) })
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> a <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> b <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> c
}</span></pre><pre><span style="background-color:transparent;"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size:13px;">run example (RetryPolicies.Retry 1)</span></font></span><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">
</span></pre><div><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><br></span></div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=60535" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxMonadic Memoization in F# (The Continuation)https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/09/05/monadic-memoization-in-f-the-continuation.aspx2010-09-06T04:13:00Z2010-09-06T04:13:00Z<div>Συνεχίζοντας τις περιπέτειες μου στον χώρο του monadic memoization, αποφάσισα να </div><div>εμπλουτίσω την προηγουμενη προσπάθειά μου με το Continuation Monad, έτσι ώστε να έχω tail <span class="Apple-style-span" style="font-size:13.3333px;">calls και να αποφύγω "περίεργα" stack overflows.</span></div><div><span class="Apple-style-span" style="font-size:13.3333px;"><br></span></div><div>Η ιδέα είναι να συνδυάσω το State Monad με το Continuation Monad (StateT Monad Transformer) και ως "δια μαγείας" όλα να δουλέψουν.</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">type StateContMonad<'s, 'a, 'r> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad of ('s -> ('s -> 'a -> 'r) -> 'r)
type StateContBuilder() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
member self.Return value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad (fun state k -> k state value)
member self.Bind(StateContMonad contStateMonad, f) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad (fun state k -> contStateMonad state (fun state' value -> let (StateContMonad contMonad') <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f value <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> contMonad' state' k))
member self.Delay( f : unit -> StateContMonad<'s, 'a, 'r> ) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad (fun state k -> let (StateContMonad contStateMonad) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f () <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> contStateMonad state k)
let memo <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> StateContBuilder()
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val Y : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b</span>
let rec Y f value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (Y f) value
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val check : 'a -> StateContMonad<Map<'a,'r>,'r option,'r> when 'a : comparison</span>
let check (value : 'a) : StateContMonad<Map<'a, 'r>, option<'r>, 'r> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad (fun map k -> k map (Map.tryFind value map))
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val store : 'a * 'r -> StateContMonad<Map<'a,'r>,unit,'r> when 'a : comparison</span>
let store (argument : 'a, result : 'r) : StateContMonad<Map<'a, 'r>, unit, 'r> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateContMonad (fun map k -> k (Map.add argument result map) ())
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val memoize : ('a -> StateContMonad<Map<'a,'b>,'b,'b>) -> 'a -> StateContMonad<Map<'a,'b>,'b,'b> when 'a : comparison</span>
let memoize f argument <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
memo {
let! checkResult <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> check argument
match checkResult with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Some result -> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> result
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> None ->
let! result <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f argument
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>! store (argument, result)
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> result
}
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val execute : (('a -> StateContMonad<Map<'a,'b>,'b,'b>) -> 'a -> StateContMonad<Map<'a,'b>,'b,'b>) -> 'a -> 'b when 'a : comparison</span>
let execute f n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> let (StateContMonad contStateMonad) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Y (memoize << f) n <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> contStateMonad Map.empty (fun _ value -> value)
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val big : int -> BigInteger</span>
let big (value : <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span>) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> System.Numerics.BigInteger(value)
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val fib : (BigInteger -> StateContMonad<'a,BigInteger,'b>) -> BigInteger -> StateContMonad<'a,BigInteger,'b></span>
let fib f n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span> n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> big 0 then memo { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> big 0 }
elif n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> big 1 then memo { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> big 1 }
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">else</span>
memo {
let! nMinus1Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> big 1)
let! nMinus2Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> big 2)
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> nMinus1Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">+</span> nMinus2Fib
}
execute fib (big 100000)</span></pre><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=59883" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxMonadic Memoization in F#https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/08/16/monadic-memoization-in-f.aspx2010-08-17T05:38:00Z2010-08-17T05:38:00Z<div>Πρόσφατα χρειάστηκε να χρησιμοποιήσω μια memoization συνάρτηση για ένα πρόβλημα δυναμικού προγραμματισμού.</div><div><span class="Apple-style-span" style="font-size:13.3333px;">Υλοποιώντας την κλασσική τεχνική χρειαζόμαστε μια συνάρτηση σαν την παρακάτω:</span></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">let memoize f <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
let cache <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> Dictionary<_, _>()
(fun x -> match cache.TryGetValue(x) with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>, y -> y
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> _ -> let v <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f(x)
cache.Add(x, v)
v)</span></pre><br></div><div><br></div><div>Το πρόβλημα με την παραπάνω συνάρτηση είναι ότι χρειαζόμαστε "κριμένα" side effects.</div><div><span class="Apple-style-span" style="font-size:13.3333px;">Μετά από μελέτη κατέληξα ότι η pure functional λύση θα περιελάμβανε τον Y combinator και το State Monad.</span></div><div><br></div><div>Η κεντρική ιδέα είναι να μετατρέψουμε μια συνάρτηση από a -> b σε a -> m b,</div><div>plus ότι χρειαζόμαστε να κάνουμε abstract και τις αναδρομικές κλήσεις για να εισάγουμε τους ελεγχους στα arguments.</div><div><br></div><div>My F# solution:</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">type StateMonad<'a, 's> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateMonad of ('s -> ('a <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">*</span> 's))
type StateBuilder() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
member self.Return value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateMonad (fun state -> (value, state))
member self.Bind (StateMonad stateMonad, f) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateMonad (fun state -> let value, state' <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> stateMonad state <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> let (StateMonad stateMonad') <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f value <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> stateMonad' state')
let memo <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> StateBuilder()
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val Y : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b</span>
let rec Y f value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (Y f) value
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val check : 'a -> StateMonad<'r option,Map<'a,'r>> when 'a : comparison</span>
let check (value : 'a) : StateMonad<option<'r>, Map<'a, 'r>> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateMonad (fun map -> (Map.tryFind value map, map))
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val store : 'a * 'r -> StateMonad<unit,Map<'a,'r>> when 'a : comparison</span>
let store (argument : 'a, result : 'r) : StateMonad<unit, Map<'a, 'r>> <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> StateMonad (fun map -> ((), Map.add argument result map))
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val memoize :('a -> StateMonad<'b,Map<'a,'b>>) -> 'a -> StateMonad<'b,Map<'a,'b>> when 'a : comparison</span>
let memoize f argument <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
memo {
let! checkResult <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> check argument
match checkResult with
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> Some result -> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> result
<span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">|</span> None ->
let! result <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f argument
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">do</span>! store (argument, result)
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> result
}
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val execute : (('a -> StateMonad<'b,Map<'a,'b>>) -> 'a -> StateMonad<'b,Map<'a,'b>>) -> 'a -> 'b when 'a : comparison</span>
let execute f n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> let (StateMonad stateMonad) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Y (memoize << f) n <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> fst (stateMonad Map.empty)
<span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">// val fib : (int -> StateMonad<int,'a>) -> int -> StateMonad<int,'a></span>
let fib f n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span> n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> 0 then memo { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> 0 }
elif n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> 1 then memo { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> 1 }
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">else</span>
memo {
let! nMinus1Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> 1)
let! nMinus2Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> f (n <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">-</span> 2)
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> nMinus1Fib <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">+</span> nMinus2Fib
}
execute fib 1000</span></pre>References:</div><div><span class="Apple-style-span" style="font-family:Tahoma, Arial, Helvetica;font-size:10px;"><a href="http://www.cs.utexas.edu/~wcook/Drafts/2006/MemoMixins.pdf">http://www.cs.utexas.edu/~wcook/Drafts/2006/MemoMixins.pdf</a></span></div><div><span class="Apple-style-span" style="font-family:Tahoma, Arial, Helvetica;font-size:10px;"><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.16.3065">http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.16.3065</a></span></div><div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=59672" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxClojure's Atoms in F#https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/07/11/clojure-s-atoms-in-f.aspx2010-07-12T02:49:00Z2010-07-12T02:49:00Z<div>Μελετώντας την <a href="http://clojure.org/">Clojure</a>, την προσοχή μου τράβηξε ένα απλό αλλά πολύ χρήσιμο construct, το <a href="http://clojure.org/atoms">Atom</a>.</div><div>Το Atom φαίνεται να είναι το πάντρεμα των ref cells της ML με lock free <a href="http://en.wikipedia.org/wiki/Compare-and-swap">CAS</a> concurrency semantics.</div><div>Επειδή τέτοια constructs είναι πολύ χρήσιμα στην F#, σκέφτηκα να υλοποιήσω κάτι ανάλογο.</div><div>My attempt:</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">type Atom<'a when 'a : not <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">struct</span>>(value : 'a) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
let refCell <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">ref</span> value
let rec swap f <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
let currentValue <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> !refCell
let result <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Interlocked.CompareExchange<'a>(refCell, f currentValue, currentValue)
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span> obj.ReferenceEquals(result, currentValue) then ()
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">else</span> Thread.SpinWait 20; swap f
member self.Value with get() <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> !refCell
member self.Swap (f : 'a -> 'a) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> swap f
let atom value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> Atom<_>(value)
let (!) (atom : Atom<_>) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
atom.Value
let swap (atom : Atom<_>) (f : _ -> _) <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span>
atom.Swap f</span></pre><div>Και ως παράδειγμα χρήσης, σκέφτηκα έναν απλό multithreaded counter.</div><div>(Σημείωση: βάζω το int μέσα στο lambda επειδή πρέπει να δώσω στο Atom ένα reference type)</div></div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">let counter <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> atom (fun () -> 0)
let listOfIncrementAsync <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> [ <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">for</span> _ <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">in</span> [1..1000000] -> async { swap counter (fun f -> (fun result () -> result <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">+</span> 1) <| f()) } ]
listOfIncrementAsync |> Async.Parallel |> Async.Run |> ignore
printfn <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"%d"</span> ((!counter)()) //</span><span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;">1000000</span></pre><br></div><div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=59421" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxF# is out therehttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/06/13/f-is-out-there.aspx2010-06-14T01:59:00Z2010-06-14T01:59:00Z<div>Εδώ και πολλά χρονια ονειρευόμουν την μέρα που κάποια απόγονος της ML θα καταφέρει να σπάσει τα ακαδημαϊκά δεσμά της και να αποκτήσει μια ευρύτερη πιο γενική αντιμετώπιση.</div><div><br></div><div>Το όνειρο αυτό έγινε πραγματικότητα (υπό μια έννοια)!!! </div><div>Η F# είναι πλέον γεγονός και βρίσκεται εγκατεστημένη με κάθε VS 2010.</div><div><span class="Apple-style-span" style="font-family:arial, sans-serif;font-size:small;line-height:15px;"><em style="font-style:normal;">Ήδη</em></span> στην εταιρία μου, κλείνουμε μια εβδομάδα λειτουργίας ενός απαιτητικού production server που τρέχει mission critical components γραμμένα σε F#.</div><div><br></div><div>Όσοι φίλοι αισθάνονται ότι πρέπει να υπάρχει κάτι περισσότερο από τα συνηθισμένα "{};++", τότε μπορούν να δώσουν μια ευκαιρία σε κάτι διαφορετικό. </div><div>Μετά από ένα σημείο θα αρχίσουν να βλέπουν τον κώδικα με άλλα μάτια... Σαν τον Neo στο τέλος του πρώτου Matrix <img src="http://www.dotnetzone.gr/cs/emoticons/emotion-15.gif" alt="Geeked" />.</div><div><br></div><div>Resources:</div><div><div>Use case:</div><div><a href="http://www.microsoft.com/casestudies/case_study_detail.aspx?casestudyid=4000005226">http://www.microsoft.com/casestudies/case_study_detail.aspx?casestudyid=4000005226</a></div><div><br></div><div>Lectures: (Όσοι φίλοι παρακολουθήσουν τα μαθήματα και έχουν ερωτήσεις - απορίες, μπορούν να μου στείλουν ένα μήνυμα και θα είναι πραγματικά χαρά μου να βοηθήσω)</div><div><a href="http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-1-of-3/">http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-1-of-3/</a></div><div><a href="http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-2-of-3/">http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-2-of-3/</a></div><div><a href="http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/">http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/</a></div></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=59104" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxΑ programming puzzle: My solutionhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/06/07/programming-puzzle-my-solution.aspx2010-06-07T19:45:00Z2010-06-07T19:45:00ZΗ λύση που έστειλα είναι η Solution2 του darklynx...<div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">class</span> Thunk<T>
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">private</span> Func<T> func;
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> T Value
{
get { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> func(); }
}
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> Thunk(Func<T> computeFunc)
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span>.func <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> () => { func <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> ((Func<T, Func<T>>)(value => () => value))(computeFunc()); <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> func(); };
}
}</span></pre>Η τεχνική αυτή μοιάζει λίγο με <a href="http://www.codeproject.com/kb/dotnet/ThereAndBackAgain.aspx">Jit thunks</a>.</div><div>Happy hacking.</div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=59014" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxΑ programming puzzlehttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/06/06/programming-puzzle.aspx2010-06-07T01:30:00Z2010-06-07T01:30:00Z<div>Πριν από λίγες μέρες, ένας φίλος μου έστειλε ένα programming puzzle που του τέθηκε κατά την διάρκεια ενός job interview.</div><div><br></div><div>Το σκέφτηκα για λίγο και του έστειλα μια πρόχειρη λύση.</div><div>Με το που είδε τον κώδικα που του έστειλα, μου απάντησε ότι αποκλείεται να είχαν κάτι τέτοιο στο μυαλό τους.</div><div><br></div><div>Επειδή είμαι περίεργος να δω και άλλες ιδέες για το πρόβλημα, όσοι φίλοι</div><div>θέλουν, μπορούν να αφήσουν ένα comment με τις ιδέες τους. </div><div>Σε επόμενο blog post, θα δώσω την λύση που του έστειλα.</div><div><br></div><div><div>Το puzzle:</div><div>Δώστε μια εναλλακτική υλοποίηση της παρακάτω class χωρίς να χρησιμοποιηθεί</div><div>κανενός είδους conditional logic construct (if, switch, ()?).</div></div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">class</span> Thunk<T>
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">private</span> T value;
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">private</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">bool</span> flag <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>;
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">private</span> Func<T> func;
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> T Value
{
get
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">if</span>(!flag)
{
value <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> func();
flag <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>;
}
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> value;
}
}
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> Thunk(Func<T> func)
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span>.func <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> func;
}
}</span></pre><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=58991" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxPattern matching in C# (The Scheme way)https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/04/10/pattern-matching-in-c-the-scheme-way.aspx2010-04-10T19:56:00Z2010-04-10T19:56:00Z<div>Με αφορμή αυτό το <a href="http://www.dotnetzone.gr/cs/forums/58014/ShowThread.aspx">thread</a>, και επειδή ο ξεχασμένος Scheme hacker που κρύβω μέσα μου επαναστάτησε... </div><div>σκέφτηκα να συνδυάσω old time classic Scheme hacking και modern C# style API.</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><pre><font class="Apple-style-span" color="#0000FF" face="'Courier New'"><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">class</span> PatternMatch
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> Func<Func<TValue, TResult>, Func<TValue, TResult>> With<TValue, TResult>(Func<TValue, <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">bool</span>> condition, Func<TValue, TResult> action)
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> With(value => value, condition, action);
}
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> Func<Func<TValue, TResult>, Func<TValue, TResult>> With<TValue, TResult>(<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span> Func<Func<TValue, TResult>, Func<TValue, TResult>> withFunc, Func<TValue, <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">bool</span>> condition, Func<TValue, TResult> action)
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> continuation => withFunc(value => condition(value) ? action(value) : continuation(value));
}
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">public</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">static</span> Func<TValue, TResult> Else<TValue, TResult>(<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span> Func<Func<TValue, TResult>, Func<TValue, TResult>> withFunc, Func<TValue, TResult> elseFunc)
{
<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">return</span> withFunc(elseFunc);
}
}</span></pre><br></font></pre>Example:</span></pre><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">var pattern <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> PatternMatch.With<<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">int</span>, <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">string</span>>(value => value == 1, value => <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"One "</span>)
.With(value => value == 2, value => <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Two "</span>)
.With(value => value == 3, value => <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Three "</span>)
.Else(_ => <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Else"</span>);
Console.WriteLine(pattern(1));</span></pre>
<span class="Apple-style-span" style="font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif;white-space:normal;font-size:13px;">Καλό Σάββατο σε όλους μας.</span></span></pre></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=58020" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxRobin Milner (13/1/1934 - 20/3/2010)https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/04/01/robin-milner-13-1-1934-20-3-2010.aspx2010-04-01T21:48:00Z2010-04-01T21:48:00ZΗ <a href="http://en.wikipedia.org/wiki/ML_programming_language">ML</a> είναι μια από τις γλώσσες που άλλαξαν εντελώς τον τρόπο σκέψης μου.<div><div>Ο <a href="http://en.wikipedia.org/wiki/Robin_Milner">Robin Milner</a> είναι ένας από εκείνους τους σπάνιους ανθρώπους, που ανέδειξαν το βάθος, την δύναμη και την ομορφιά στο </div><div>αντικείμενο που σήμερα ονομάζουμε Computer Science.</div><div>Μια προσωπικότητα larger than life.</div><div><br></div><div><img src="http://www.simple-talk.com/iwritefor/articlefiles/899-RobinMilner.jpg"></div></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=57926" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxReactive Monadshttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/02/27/reactive-monads.aspx2010-02-27T22:06:00Z2010-02-27T22:06:00Z<div><br></div><div><img src="http://upload.wikimedia.org/wikipedia/en/9/98/ErikMeijer.jpg" style="width:400px;"></div><div>Το Rx είναι το νέο δημιούργημα του Erik Meijer, και μετά από μήνες ενασχόλησης μαζί του, νομίζω ότι είναι απλά 'a work of genius'.</div><div>Αυτό που κάνει είναι να δρα ως compositional glue για events, asynchronous calls και γενικά για push based computations.</div><div><br></div><div>Κατεβάστε το από <a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx">εδώ </a>και αρχίστε να εξερευνείτε τις δυνατότητές του (You will be amazed).</div><div><br></div><div>Ως ένα παράδειγμα της μαγείας του, έγραψα ένα κλασσικό mouse move recording and playback.</div><div><br></div><div><pre><span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"><span class="Apple-tab-span" style="white-space:pre;"> </span> var mouseMoveObservable <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> Observable.Merge(<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> Control[] { <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span>, recordButton, stopButton, playButton }
<span class="Apple-tab-span" style="white-space:pre;"> </span>.Select(control => Observable.FromEvent<MouseEventArgs>(control, <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"MouseMove"</span>)));
ReplaySubject<TimeInterval<IEvent<MouseEventArgs>>> replayObservable <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">null</span>;
Observable.FromEvent<EventArgs>(recordButton, <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Click"</span>).ObserveOnWindowsForms().Subscribe(_ =>
{
stopButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>; recordButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>;
replayObservable <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> mouseMoveObservable.TimeInterval().Record();
replayObservable.ObserveOnWindowsForms().Subscribe(time => <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">this</span>.Text <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> String.Format(<span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"{0},{1}"</span>, time.Value.EventArgs.X, time.Value.EventArgs.Y));
});
Observable.FromEvent<EventArgs>(stopButton, <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Click"</span>).ObserveOnWindowsForms().Subscribe(_ =>
{
replayObservable.Dispose();
stopButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>; playButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>;
});
Observable.FromEvent<EventArgs>(playButton, <span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;">"Click"</span>).ObserveOnWindowsForms().Subscribe(_ =>
{
playButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">false</span>;
var playObservable <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> replayObservable.ToEnumerable()
.Aggregate(Observable.Return(<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> Unit()),
(accObservable, timeMouse) => accObservable.Delay(timeMouse.Interval)
.ObserveOnWindowsForms()
.Do(__ => Cursor.Position <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> ((Control)timeMouse.Value.Sender).PointToScreen(<span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">new</span> Point(timeMouse.Value.EventArgs.X, timeMouse.Value.EventArgs.Y))));
playObservable.Subscribe(value => { }, () => recordButton.Enabled <span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">=</span> <span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;">true</span>);
});</span></pre><br></div><div><br></div><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=57356" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxLiftM'e' up Scottyhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/02/07/liftm-e-up-scotty.aspx2010-02-08T07:40:00Z2010-02-08T07:40:00Z<P>Έχοντας αναπτύξει όλο το απαραίτητο machinery (<A href="http://www.dotnetzone.gr/cs/blogs/palladin/archive/2009/12/20/abstracting-over-m-in-f.aspx">1</A>, <A href="http://www.dotnetzone.gr/cs/blogs/palladin/archive/2010/01/17/abstracting-over-m-generic-functions.aspx">2</A>), μπορούμε να συνεχίσουμε με την ίδια αφαιρετική διάθεση και να "ανεβάσουμε" στον κόσμο του 'M', <BR>συναρτήσεις με ένα, δυο ή περισσότερα arguments.</P><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// liftM declarations</SPAN>
let liftM<'M, 'A1, 'R when 'M :> MonadDef<'M>> (m : MonadDef<'M>) (f : 'A1 -> 'R)
(a : IMonad<'A1, 'M>) : IMonad<'R, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m.Map(f, a)
let liftM2<'M, 'A1, 'A2, 'R when 'M :> MonadDef<'M>> (m : MonadDef<'M>) (f : 'A1 -> 'A2 -> 'R)
(a : IMonad<'A1, 'M>) (b : IMonad<'A2, 'M>) : IMonad<'R, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m.Apply(liftM m f a, b)
let liftM3<'M, 'A1, 'A2, 'A3, 'R when 'M :> MonadDef<'M>> (m : MonadDef<'M>) (f : 'A1 -> 'A2 -> 'A3 -> 'R)
(a : IMonad<'A1, 'M>) (b : IMonad<'A2, 'M>)
(c : IMonad<'A3, 'M>) : IMonad<'R, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m.Apply(liftM2 m f a b, c)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">//liftM example</SPAN>
let result <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> liftM2 listM (<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN>) (listM.OfList [0; 1]) (listM.OfList [0; 2])
printfn <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"%A"</SPAN> result <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">//[0; 2; 1; 3]</SPAN></SPAN></PRE>
<P>Haskell inspiration<BR><A href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Monad.html">http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Monad.html</A></P>
<P> </P><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=56993" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxAbstracting over 'M' (generic functions)https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2010/01/17/abstracting-over-m-generic-functions.aspx2010-01-18T04:17:00Z2010-01-18T04:17:00Z<P>(Haskell ideas => F# (OOP + FP))</P>
<P>Στην Haskell, επειδή έχουμε higher kind polymorphism, μπορούμε να ορίσουμε κάποιες πολύ χρήσιμες και αρκετά γενικές συναρτήσεις για Monads.<BR>Σκέφτηκα να προσπαθήσω να κάνω κάτι αντίστοιχο σε F# (υλοποιώντας ένα Generic List Monad) και να ορίσω τις κλασσικές sequence, mapM, filterM.</P>
<P>Ως παράδειγμα της δύναμης που μας προσφέρει η αφαίρεση, μπορούμε να ορίσουμε την συνάρτηση του powerset ως εξής:<BR><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">let powerSet xs <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> listM.FilterM ((fun _ -> listM.OfList [<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">false</SPAN>; <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">true</SPAN>]), listM.OfList xs) <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// it's magic</SPAN></SPAN></P>
<P><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN class=Apple-style-span style="WORD-SPACING:0px;FONT:medium 'Times New Roman';TEXT-TRANSFORM:none;TEXT-INDENT:0px;WHITE-SPACE:normal;LETTER-SPACING:normal;BORDER-COLLAPSE:separate;orphans:2;widows:2;-webkit-border-horizontal-spacing:0px;-webkit-border-vertical-spacing:0px;-webkit-text-decorations-in-effect:none;-webkit-text-size-adjust:auto;-webkit-text-stroke-width:0px;"><SPAN class=Apple-style-span style="FONT-SIZE:13px;FONT-FAMILY:monospace;"><FONT face=Tahoma color=#000000 size=2>Χρησιμοποιώντας subtype polymorphism και μερικά περιορισμένα downcasts, καταφέραμε να φέρουμε λίγο από το άρωμα και την αίγλη της Haskell στον κόσμο της F#.</FONT></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN class=Apple-style-span style="WORD-SPACING:0px;FONT:medium 'Times New Roman';TEXT-TRANSFORM:none;TEXT-INDENT:0px;WHITE-SPACE:normal;LETTER-SPACING:normal;BORDER-COLLAPSE:separate;orphans:2;widows:2;-webkit-border-horizontal-spacing:0px;-webkit-border-vertical-spacing:0px;-webkit-text-decorations-in-effect:none;-webkit-text-size-adjust:auto;-webkit-text-stroke-width:0px;"><SPAN class=Apple-style-span style="FONT-SIZE:13px;FONT-FAMILY:monospace;"><FONT face=Tahoma color=#000000 size=2>Happy hacking...</FONT></SPAN></SPAN></SPAN></SPAN></P><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">module MonadModule <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">//Generic Monad Definition</SPAN>
[<AbstractClass>]
type MonadDef<'M when 'M :> MonadDef<'M>>() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">as</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
let (>>=) m f <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Bind(m, f)
let unit v <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Return v
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> let listDef <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> ListDef()
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> member Return<'T> : 'T -> IMonad<'T,'M>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> member Bind<'T, 'S> : IMonad<'T,'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">*</SPAN> ('T -> IMonad<'S,'M>) -> IMonad<'S,'M>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> member Zero<'T> : unit -> IMonad<'T,'M>
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Delay(f) <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> unit () >>= fun () -> f()
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Combine<'T>(first : IMonad<unit, 'M>, second : IMonad<'T, 'M>) : IMonad<'T, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Then (first, second)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Then<'T, 'S>(firstM : IMonad<'T, 'M>, secondM : IMonad<'S, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
firstM >>= fun _ -> secondM
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Map<'T, 'S>(f : 'T -> 'S, m : IMonad<'T, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m >>= fun v -> unit (f v)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Apply<'T, 'S>(mf : IMonad<'T -> 'S, 'M>, m : IMonad<'T, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
mf >>= fun f -> m >>= fun v -> unit (f v)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Join<'T>(m : IMonad<IMonad<'T, 'M>, 'M>) : IMonad<'T, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m >>= id
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Sequence<'T>(lm : IMonad<IMonad<'T, 'M>, ListDef>) : IMonad<IMonad<'T, ListDef>, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
match lm :?> _ with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nil -> unit (Nil :> _)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Cons (m, ms) -> m >>= fun v -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Sequence ms >>= fun vs -> unit (listDef.ConsM v vs)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.MapM<'T, 'S>(f : 'T -> IMonad<'S, 'M>, l : IMonad<'T, ListDef>) : IMonad<IMonad<'S, ListDef>, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Sequence (listDef.Map ((fun v -> f v), l))
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.FilterM<'T>(p : 'T -> IMonad<<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">bool</SPAN>, 'M>, l : IMonad<'T, ListDef>) : IMonad<IMonad<'T, ListDef>, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
match l :?> _ with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nil -> unit (Nil :> _)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Cons (x, xs) -> p x >>= fun b -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.FilterM (p, xs) >>= fun ys -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">if</SPAN> b then unit (listDef.ConsM x ys) <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">else</SPAN> unit ys
and IMonad<'T,'M when 'M :> MonadDef<'M>> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">interface</SPAN> end
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// List Monad</SPAN>
and List<'T> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nil
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Cons of ('T <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">*</SPAN> List<'T>)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">interface</SPAN> IMonad<'T, ListDef>
and
ListDef() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
inherit MonadDef<ListDef>() with
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.OfList<'T>(xs : list<'T>) : IMonad<'T, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
List.foldBack (fun v acc -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.ConsM v acc) xs <| <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Zero()
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.ConsM (x : 'T) (acc : IMonad<'T, ListDef>) : IMonad<'T, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> Cons (x, acc :?> _) :> _
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Foldr<'T, 'S>(f : 'T -> 'S -> 'S, seed : 'S, list : IMonad<'T, ListDef>) : 'S <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
match list :?> _ with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nil -> seed
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Cons (x, xs) -> f x (<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Foldr (f, seed, xs) )
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Concat<'T>(first : IMonad<'T, ListDef>, second : IMonad<'T, ListDef>) : IMonad<'T, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Foldr(<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.ConsM, second, first)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Return<'T>(v : 'T) : IMonad<'T, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Cons (v, Nil) :> _
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Bind<'T,'S>(m : IMonad<'T, ListDef>, f : 'T -> IMonad<'S, ListDef>) : IMonad<'S, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Foldr ((fun x acc -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Concat (f x, acc)), Nil :> _, m)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Zero<'T>() : IMonad<'T, ListDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Nil :> _
let listM <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> ListDef()
open MonadModule
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// Maybe Monad</SPAN>
module MaybeModule <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
type Maybe<'T> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nothing
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Just of 'T
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">interface</SPAN> IMonad<'T, MaybeDef>
and
MaybeDef() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
inherit MonadDef<MaybeDef>() with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Return<'T>(v : 'T) : IMonad<'T, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Just v :> _
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Bind<'T,'S>(m : IMonad<'T, MaybeDef>, f : 'T -> IMonad<'S, MaybeDef>) : IMonad<'S, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
match m :?> _ with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nothing -> Nothing :> _
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Just x -> f x
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Zero<'T>() : IMonad<'T, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Nothing :> _
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Just<'T>(value : 'T) : IMonad<'T, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Just value :> _
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Nothing<'T>() : IMonad<'T, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Nothing :> _
let maybeM <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> MaybeDef()
open MaybeModule
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">//Examples</SPAN>
let test <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> listM.OfList [ maybeM.Just 1; maybeM.Just 2 ]
maybeM.Sequence test |> printfn <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"%A"</SPAN>
let powerSet xs <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> listM.FilterM ((fun _ -> listM.OfList [<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">false</SPAN>; <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">true</SPAN>]), listM.OfList xs)
powerSet [1..3] |> printfn <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"%A"</SPAN></SPAN></PRE></SPAN></SPAN><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=56469" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxOnly for language geekshttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/12/27/only-for-language-geeks.aspx2009-12-27T22:03:00Z2009-12-27T22:03:00Z<P>No comment</P>
<P><IMG src="http://imgur.com/P9RnL.jpg"></P><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=56082" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxAbstracting over 'M' (in F#)https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/12/20/abstracting-over-m-in-f.aspx2009-12-20T23:53:00Z2009-12-20T23:53:00Z<P>Μετά από αρκετές αποτυχημένες προσπάθειες, στο να συνδυάσω <A href="http://www.dotnetzone.gr/cs/blogs/palladin/archive/2009/10/25/abstracting-over-m.aspx">Type constructor polymorphism</A> και LINQ syntax, αποφάσισα <BR>να δοκιμάσω τις ίδιες ιδέες σε F#.</P>
<P>Η F# υλοποίηση είναι ακριβώς ίδια με την αντίστοιχη σε C#, με την μονη διαφορα ότι το Monad generalization δουλεύει με το ειδικό <BR>syntax support που μας παρέχουν τα computation expressions.</P><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">[<AbstractClass>]
type MonadDef<'M when 'M :> MonadDef<'M>>() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">as</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
let (>>=) m f <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Bind(m, f)
let unit v <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Return v
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> member Return<'T> : 'T -> IMonad<'T,'M>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> member Bind<'T, 'S> : IMonad<'T,'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">*</SPAN> ('T -> IMonad<'S,'M>) -> IMonad<'S,'M>
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Then<'T, 'S>(firstM : IMonad<'T, 'M>, secondM : IMonad<'S, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
firstM >>= fun _ -> secondM
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Map<'T, 'S>(f : 'T -> 'S, m : IMonad<'T, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m >>= fun v -> unit (f v)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Apply<'T, 'S>(mf : IMonad<'T -> 'S, 'M>, m : IMonad<'T, 'M>) : IMonad<'S, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
mf >>= fun f -> m >>= fun v -> unit (f v)
member <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Join<'T>(m : IMonad<IMonad<'T, 'M>, 'M>) : IMonad<'T, 'M> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
m >>= id
and IMonad<'T,'M when 'M :> MonadDef<'M>> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">interface</SPAN> end
type Maybe<'T> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nothing
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Just of 'T
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">interface</SPAN> IMonad<'T, MaybeDef>
and
MaybeDef() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
inherit MonadDef<MaybeDef>() with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Return<'T>(v : 'T) : IMonad<'T, MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
Just v :> _
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN>.Bind<'T,'S>(m : IMonad<'T, MaybeDef>, f : 'T -> IMonad<'S, MaybeDef>) : IMonad<'S,MaybeDef> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
match m :?> _ with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Nothing -> Nothing :> _
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Just x -> f x
let maybe <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> MaybeDef()
let toMaybeString a <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
maybe {
let! v <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> Just a
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> v.ToString()
}
printfn <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"%A"</SPAN> (toMaybeString 42)</SPAN></PRE><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=55975" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxΔιομήδης Σπινέλληςhttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/11/06/54972.aspx2009-11-06T22:11:00Z2009-11-06T22:11:00Z<P>Πριν πολλά πολλά χρονια... είχα αγοράσει ένα βιβλίο που είχε στο εξώφυλλο ένα ψάρι (the "<A href="http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ref=sr_1_1?ie=UTF8&s=books&qid=1257509672&sr=8-1">fish book</A>")!!!<BR>Αυτό που βρήκα περίεργο στο βιβλίο δεν ήταν το ψάρι αλλα αυτός ο κώδικας </P><PRE><SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:black;FONT-SIZE:11px;FONT-WEIGHT:normal;"><SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:green;FONT-SIZE:11px;FONT-WEIGHT:normal;">/* DDS-BASIC interpreter in "C" annotated by Michael Somos 1997 */</SPAN>
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:green;FONT-SIZE:11px;FONT-WEIGHT:normal;">/* INPUT bug fix 07Sep2005 Somos */</SPAN>
/* original by Diomidis Spinellis <SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">for</SPAN> 1990 IOCCC
<URL:http:<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:green;FONT-SIZE:11px;FONT-WEIGHT:normal;">//reality.sgi.com/csp/ioccc/1990/dds.c></SPAN>
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> O(b,f,u,s,c,a)b(){<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">int</SPAN> o=f();<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">switch</SPAN>(*p++){X u:_ o s b();X c:_ o a b();<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">default</SPAN>:p--;_ o;}}
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> t(e,d,_,C)X e:f=fopen(B+d,_);C;fclose(f)
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> U(y,z)<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(p=Q(s,y))*p++=z,*p=' '
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> N <SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">for</SPAN>(i=0;i<11*R;i++)m[ i ]&&
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> I <SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"%d %s\n"</SPAN>,i,m[ i ]
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> X ;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">break</SPAN>;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">case</SPAN>
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> _ <SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">return</SPAN>
<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">#define</SPAN> R 999
typedef <SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">char</SPAN>*A;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">int</SPAN>*C,E[R],L[R],M[R],P[R],l,i,j;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">char</SPAN> B[R],F[2];A m[12*R],malloc
(),p,q,x,y,z,s,d,f,fopen();A Q(s,o)A s,o;{<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">for</SPAN>(x=s;*x;x++){<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">for</SPAN>(y=x,z=o;*z&&*y==
*z;y++)z++;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">if</SPAN>(z>o&&!*z)_ x;}_ 0;}main(){m[11*R]<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">=</SPAN><SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"E"</SPAN>;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(puts(<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"Ok"</SPAN>),gets(B)
)<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">switch</SPAN>(*B){X'R':C=E;l=1;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">for</SPAN>(i=0;i<R;P[i++]=0);<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(l){<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(!(s=m[l]))l++;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">if</SPAN>
(!Q(s,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"\""</SPAN>)){U(<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"<>"</SPAN>,'#');U(<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"<="</SPAN>,'$');U(<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">">="</SPAN>,'!');}d=B;<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(*F=*s){*s=='<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"'&&j
++;if(j&1||!Q("</SPAN> \t<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">",F))*d++=*s;s++;}*d--=j=0;if(B[1]!='=')switch(*B){X'E':l=-1
X'R':B[2]!='M'&&(l=*--C)X'I':B[1]=='N'?gets(p=B),P[*d]=S():(*(q=Q(B,"</SPAN>TH<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"))=0,p
=B+2,S()&&(p=q+4,l=S()-1))X'P':B[5]=='"</SPAN>'?*d=0,puts(B+6):(p=B+5,printf(<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"%d\n"</SPAN>,S
()))X'G':p=B+4,B[2]=='S'&&(*C++=l,p++),l=S()-1 X'F':*(q=Q(B,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"TO"</SPAN>))=0;p=B+5;P[i
=B[3]]=S();p=q+2;M[ i ]=S();L[ i ]=l X'N':++P[*d]<=M[*d]&&(l=L[*d]);}<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">else</SPAN> p=B+2,P[
*B]=S();l++;}X'L':N printf(I)X'N':N free(m[ i ]),m[ i ]=0 X'B':_ 0 t('S',5,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"w"</SPAN>,N
fprintf(f,I))t('O',4,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"r"</SPAN>,<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">while</SPAN>(fgets(B,R,f))(*Q(B,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">"\n"</SPAN>)=0,G()))X 0:<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">default</SPAN>:G()
;}_ 0;}G(){l=atoi(B);m[l]&&free(m[l]);(p=Q(B,<SPAN style="BACKGROUND-COLOR:#e4e4e4;FONT-FAMILY:Courier New;COLOR:#666666;FONT-SIZE:11px;FONT-WEIGHT:normal;">" "</SPAN>))?strcpy(m[l]=malloc(strlen(p
)),p+1):(m[l]=0,0);}O(S,J,'<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">=</SPAN>',==,'#',!<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">=</SPAN>)O(J,K,'<',<,'>',>)O(K,V,'$',<=,'!',>=)
O(V,W,'<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">+</SPAN>',+,'<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">-</SPAN>',-)O(W,Y,'<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">*</SPAN>',*,'<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">/</SPAN>',/)Y(){<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:blue;FONT-SIZE:11px;FONT-WEIGHT:normal;">int</SPAN> o;_*p=='<SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:red;FONT-SIZE:11px;FONT-WEIGHT:normal;">-</SPAN>'?p++,-Y():*p>='0'&&*p<=
'9'?strtol(p,&p,0):*p=='('?p++,o=S(),p++,o:P[*p++];}</SPAN></PRE><PRE><SPAN style="BACKGROUND-COLOR:transparent;FONT-FAMILY:Courier New;COLOR:black;FONT-SIZE:11px;FONT-WEIGHT:normal;"><FONT size=2 face=Tahoma>Τι θέλει να πει ο ποιητής και ποιος είναι αυτός ο Διομήδης Σπινέλλης,,,μετά από κάποια χρονια έμαθα!!!<BR>Πολλά <A href="http://www.capital.gr/gmessages/showTopic.asp?id=1433722">συγχαρητήρια</A> και από εμενα...<BR>Πόσες χώρες έχουν έναν hacker σε τέτοια θέση!!!</FONT><BR></SPAN></PRE><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=54972" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxAbstracting over 'M'https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/10/25/abstracting-over-m.aspx2009-10-26T00:34:00Z2009-10-26T00:34:00Z<P>Τον τελευταίο καιρό ψάχνω κάποιο φορμαλισμό (σε C#) ώστε να μπορέσω να έχω έναν generic-reusable ορισμό ενός <A href="http://en.wikipedia.org/wiki/Monad_(functional_programming)">Monad</A>.<BR>Αυτό που λείπει από τα .Net generics είναι η δυνατότητα να έχω abstraction σε επίπεδο Type Constructor. </P>
<P>Σαν παράδειγμα της συγκεκριμένης αφαίρεσης, παρουσιάζω τον generic ορισμό ενός Monad μέσα από δυο αγαπημένες μου γλώσσες.</P><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">Haskell
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Monad m where
(>>=) :: m a -> (a -> m b) -> m b
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> :: a -> m a
Scala
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Monad[M[_]] {
def unit[T](a: T): M[T]
def bind[T, K](m: M[T], f: T => M[K]): M[K]
}</SPAN></PRE><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><FONT face=Tahoma size=2>Μετά από αρκετό πειραματισμό και <A href="http://lambda-the-ultimate.org/node/3629">μελέτη</A>, κατέληξα στον παρακάτω κώδικα.</FONT></SPAN></PRE><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Monad<T, M> where M : MonadDef<M> { }
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> MonadDef<M> where M : MonadDef<M>
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> Monad<T, M> Unit<T>(T value);
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> Monad<S, M> Bind<T, S>(Monad<T, M> monad, Func<T, Monad<S, M>> func);
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> Monad<S, M> Then<T, S>(Monad<T, M> first, Monad<S, M> second)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> Bind(first, _ => second);
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> Monad<S, M> Map<T, S>(Monad<T, M> monad, Func<T, S> f)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> Bind(monad, value => Unit(f(value)));
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> Monad<T, M> Join<T>(Monad<Monad<T, M>, M> monad)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> Bind(monad, value => value);
}
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// Maybe Monad implementation </SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">abstract</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Maybe<T> : Monad<T, MaybeDef>
{
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">sealed</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Just<T> : Maybe<T>
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> T Value { <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">private</SPAN> set; get; }
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> Just(T value) { Value <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> value; }
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">sealed</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> Nothing<T> : Maybe<T> { }
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> MaybeMonadExtensions
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> Maybe<T> ToMaybe<T>(<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN> Monad<T, MaybeDef> monad)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> (Maybe<T>)monad;
}
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">sealed</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">class</SPAN> MaybeDef : MonadDef<MaybeDef>
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> Monad<T, MaybeDef> Unit<T>(T value)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> Just<T>(value);
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">override</SPAN> Monad<S, MaybeDef> Bind<T, S>(Monad<T, MaybeDef> monad, Func<T, Monad<S, MaybeDef>> f)
{
Just<T> just <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> monad <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">as</SPAN> Just<T>;
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">if</SPAN> (just !<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">null</SPAN>)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> f(just.Value);
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">else</SPAN>
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> Nothing<S>();
}
}</SPAN></PRE><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"></SPAN> </PRE><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"> static</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">void</SPAN> Main(<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN>[] args)
{
var def <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> MaybeDef();
Maybe<<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN>> result <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> def.Bind(def.Unit(42), value => def.Unit(value.ToString())).ToMaybe();
}</SPAN></PRE></SPAN></PRE></SPAN></PRE><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=54710" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxRegEx engine in F#https://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/09/27/regex-engine-in-f.aspx2009-09-27T21:54:00Z2009-09-27T21:54:00Z<P>Ένα από τα πολύ δυνατά χαρακτηριστικά μιας functional γλώσσας, είναι η δυνατότητα να δημιουργούμε internal DSLs κάνοντας compose combinators.</P>
<P>Ένα τέτοιο παράδειγμα, είναι μια regex engine που έγραψα σε F#.</P>
<P>Κάποιες βασικές ιδέες της υλοποίησης:<BR> - lazy computations for backtracking<BR> - combinators for regex composition<BR> - parametric polymorphism: Generic "named capture variables" and input sequences <BR> - Unions + Active Patterns: pattern matching and value extraction</P>
<P><BR>Ακολουθεί ένα sample</P><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">#r <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"FSharp.PowerPack.dll"</SPAN>
#load <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"RegEx.fs"</SPAN>
open System
open RegEx
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// example from http://www.martinfowler.com/bliki/ComposedRegex.html</SPAN>
type extractTags <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> NumberOfPoint of <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">int</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> NumberOfNights of <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">int</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> HotelName of <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN>
let numberOfPoints <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> toInt >> NumberOfPoint
let numberOfNights <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> toInt >> NumberOfNights
let hotelName <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> toString >> HotelName
let scoreKeyword() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"score"</SPAN> => !<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> space()
let numberOfPoints <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> !<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> digit() |> group numberOfPoints
let forKeyword() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> space() => <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"for"</SPAN> => space()
let numberOfNights <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> !<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> digit() |> group numberOfNights
let nightsAtKeyword() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> spaces() => <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"nights"</SPAN> => spaces() => <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">string</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"at"</SPAN> => spaces()
let hotelName() <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> !<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> any() |> group hotelName
let pattern <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> scoreKeyword() => numberOfPoints => forKeyword() => numberOfNights => nightsAtKeyword() => hotelName() => endOfLine()
let text <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> List.reduce (fun acc value -> acc <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"\r\n "</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> value)
[ <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"score 400 for 2 nights at Minas Tirith Airport"</SPAN>;
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"score 500 for 6 nights at Athens Airport"</SPAN>;
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"score 200 for 3 nights at London Airport"</SPAN> ] <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"\r\n"</SPAN>
let result <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> patternMatch pattern text
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:green;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">// pattern match</SPAN>
match result with
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Success ( (NumberOfPoint(points) :: NumberOfNights(nights) :: HotelName(name) :: _) :: _ ) -> printfn <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"Points: %d, Nights %d, Hotel name: %s"</SPAN> points nights name
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> Failure -> ()
let replacePattern <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> function
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> [NumberOfPoint(points); NumberOfNights(nights); HotelName(name)] -> sprintf <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"score %d for %d nights at %s"</SPAN> (points <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">*</SPAN> 2) (nights <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">*</SPAN> 3) (name <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">+</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">" ok"</SPAN>)
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">|</SPAN> _ -> failwith <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:#666666;FONT-FAMILY:Courier New;BACKGROUND-COLOR:#e4e4e4;">"Expected extraction pattern: score {NumberOfPoint} for {NumberOfNights} nights at {HotelName}"</SPAN>
let replacedResult <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> patternReplace pattern text replacePattern |> Array.of_seq |> (fun (chars : array<<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">char</SPAN>>) -> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> String(chars))</SPAN></PRE><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=54018" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspxletrechttps://www.dotnetzone.gr:443/cs/blogs/palladin/archive/2009/09/13/letrec.aspx2009-09-14T05:44:00Z2009-09-14T05:44:00Z<P>Ο Bart de smet συνεχίζει την πολύ καλή σειρά από posts, και αυτή την φορα μας παρουσιάζει ένα <A href="http://community.bartdesmet.net/blogs/bart/archive/2009/09/12/taming-your-sequence-s-side-effects-through-ienumerable-let.aspx">cache Enumerable</A>, μαζί με έναν "let" binder.<BR>Φυσικά λείπει το αδελφάκι "letrec", όπου έμεινε ως άσκηση για τον αναγνώστη.<BR>(η αφορμή που έψαχνα για να ξυπνήσει Ο old schemer μέσα μου)</P><PRE><SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:black;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;"> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">delegate</SPAN> Func<A, R> Recursive<A, R>(Recursive<A, R> r);
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f)
{
Recursive<A, R> rec <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> r => a => f(r(r))(a);
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> rec(rec);
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> IEnumerable<U> Let<T, U>(<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN> IEnumerable<T> source, Func<IEnumerable<T>, IEnumerable<U>> function)
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">using</SPAN> (var mem <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">new</SPAN> MemoizeEnumerable<T>(source))
{
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">foreach</SPAN> (var item <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">in</SPAN> function(mem))
yield <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> item;
}
}
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">public</SPAN> <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">static</SPAN> IEnumerable<U> LetRec<T, U>(<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">this</SPAN> IEnumerable<T> source, Func<Func<IEnumerable<T>, IEnumerable<U>>, Func<IEnumerable<T>, IEnumerable<U>>> function)
{
Func<Func<IEnumerable<T>, IEnumerable<U>>, Func<IEnumerable<T>, IEnumerable<U>>> letWrap <SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:red;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">=</SPAN>
f => x => Let(x, function(f));
<SPAN style="FONT-WEIGHT:normal;FONT-SIZE:11px;COLOR:blue;FONT-FAMILY:Courier New;BACKGROUND-COLOR:transparent;">return</SPAN> Y(letWrap)(source);
}</SPAN></PRE><img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=53698" width="1" height="1">PALLADINhttps://www.dotnetzone.gr:443/cs/members/PALLADIN.aspx