summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dart.html.markdown506
-rw-r--r--fsharp.html.markdown431
-rw-r--r--haskell.html.markdown25
3 files changed, 953 insertions, 9 deletions
diff --git a/dart.html.markdown b/dart.html.markdown
new file mode 100644
index 00000000..d064dc7d
--- /dev/null
+++ b/dart.html.markdown
@@ -0,0 +1,506 @@
+---
+language: Dart
+author: Joao Pedrosa
+author_url: https://github.com/jpedrosa/
+---
+
+Dart is a newcomer into the realm of programming languages.
+It borrows a lot from other mainstream languages, having as a goal not to deviate too much from
+its JavaScript sibling. Like JavaScript, Dart aims for great browser integration.
+
+Dart's most controversial feature must be its Optional Typing.
+
+```javascript
+import "dart:collection";
+import "dart:math" as DM;
+
+// Welcome to Learn Dart in 15 minutes. http://www.dartlang.org/
+// This is an executable tutorial. You can run it with Dart or on
+// the Try Dart! site if you copy/paste it there. http://try.dartlang.org/
+
+// Function declaration and method declaration look the same. Function
+// declarations can be nested. The declaration takes the form of
+// name() {} or name() => singleLineExpression;
+// The fat arrow function declaration has an implicit return for the result of
+// the expression.
+example1() {
+ example1nested1() {
+ example1nested2() => print("Example1 nested 1 nested 2");
+ example1nested2();
+ }
+ example1nested1();
+}
+
+// Anonymous functions don't include a name.
+example2() {
+ example2nested1(fn) {
+ fn();
+ }
+ example2nested1(() => print("Example2 nested 1"));
+}
+
+// When a function parameter is declared, the declaration can include the
+// number of parameters the function takes by specifying the names of the
+// parameters it takes.
+example3() {
+ example3nested1(fn(informSomething)) {
+ fn("Example3 nested 1");
+ }
+ example3planB(fn) { // Or don't declare number of parameters.
+ fn("Example3 plan B");
+ }
+ example3nested1((s) => print(s));
+ example3planB((s) => print(s));
+}
+
+// Functions have closure access to outer variables.
+var example4Something = "Example4 nested 1";
+example4() {
+ example4nested1(fn(informSomething)) {
+ fn(example4Something);
+ }
+ example4nested1((s) => print(s));
+}
+
+// Class declaration with a sayIt method, which also has closure access
+// to the outer variable as though it were a function as seen before.
+var example5method = "Example5 sayIt";
+class Example5Class {
+ sayIt() {
+ print(example5method);
+ }
+}
+example5() {
+ // Create an anonymous instance of the Example5Class and call the sayIt
+ // method on it.
+ new Example5Class().sayIt();
+}
+
+// Class declaration takes the form of class name { [classBody] }.
+// Where classBody can include instance methods and variables, but also
+// class methods and variables.
+class Example6Class {
+ var example6InstanceVariable = "Example6 instance variable";
+ sayIt() {
+ print(example6InstanceVariable);
+ }
+}
+example6() {
+ new Example6Class().sayIt();
+}
+
+// Class methods and variables are declared with "static" terms.
+class Example7Class {
+ static var example7ClassVariable = "Example7 class variable";
+ static sayItFromClass() {
+ print(example7ClassVariable);
+ }
+ sayItFromInstance() {
+ print(example7ClassVariable);
+ }
+}
+example7() {
+ Example7Class.sayItFromClass();
+ new Example7Class().sayItFromInstance();
+}
+
+// Literals are great, but there's a restriction for what literals can be
+// outside of function/method bodies. Literals on the outer scope of class
+// or outside of class have to be constant. Strings and numbers are constant
+// by default. But arrays and maps are not. They can be made constant by
+// declaring them "const".
+var example8A = const ["Example8 const array"],
+ example8M = const {"someKey": "Example8 const map"};
+example8() {
+ print(example8A[0]);
+ print(example8M["someKey"]);
+}
+
+// Loops in Dart take the form of standard for () {} or while () {} loops,
+// slightly more modern for (.. in ..) {}, or functional callbacks with many
+// supported features, starting with forEach.
+var example9A = const ["a", "b"];
+example9() {
+ for (var i = 0; i < example9A.length; i++) {
+ print("Example9 for loop '${example9A[i]}'");
+ }
+ var i = 0;
+ while (i < example9A.length) {
+ print("Example9 while loop '${example9A[i]}'");
+ i++;
+ }
+ for (var e in example9A) {
+ print("Example9 for-in loop '${e}'");
+ }
+ example9A.forEach((e) => print("Example9 forEach loop '${e}'"));
+}
+
+// To loop over the characters of a string or to extract a substring.
+var example10S = "ab";
+example10() {
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 String character loop '${example10S[i]}'");
+ }
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 substring loop '${example10S.substring(i, i + 1)}'");
+ }
+}
+
+// Int and double are the two supported number formats.
+example11() {
+ var i = 1 + 320, d = 3.2 + 0.01;
+ print("Example11 int ${i}");
+ print("Example11 double ${d}");
+}
+
+// DateTime provides date/time arithmetic.
+example12() {
+ var now = new DateTime.now();
+ print("Example12 now '${now}'");
+ now = now.add(new Duration(days: 1));
+ print("Example12 tomorrow '${now}'");
+}
+
+// Regular expressions are supported.
+example13() {
+ var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$");
+ match(s) {
+ if (re.hasMatch(s)) {
+ print("Example13 regexp matches '${s}'");
+ } else {
+ print("Example13 regexp doesn't match '${s}'");
+ }
+ }
+ match(s1);
+ match(s2);
+}
+
+// Boolean expressions need to resolve to either true or false, as no
+// implicit conversions are supported.
+example14() {
+ var v = true;
+ if (v) {
+ print("Example14 value is true");
+ }
+ v = null;
+ try {
+ if (v) {
+ // Never runs
+ } else {
+ // Never runs
+ }
+ } catch (e) {
+ print("Example14 null value causes an exception: '${e}'");
+ }
+}
+
+// try/catch/finally and throw are used for exception handling.
+// throw takes any object as parameter;
+example15() {
+ try {
+ try {
+ throw "Some unexpected error.";
+ } catch (e) {
+ print("Example15 an exception: '${e}'");
+ throw e; // Re-throw
+ }
+ } catch (e) {
+ print("Example15 catch exception being re-thrown: '${e}'");
+ } finally {
+ print("Example15 Still run finally");
+ }
+}
+
+// To be efficient when creating a long string dynamically, use
+// StringBuffer. Or you could join a string array.
+example16() {
+ var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e;
+ for (e in a) { sb.write(e); }
+ print("Example16 dynamic string created with "
+ "StringBuffer '${sb.toString()}'");
+ print("Example16 join string array '${a.join()}'");
+}
+
+// Strings can be concatenated by just having string literals next to
+// one another with no further operator needed.
+example17() {
+ print("Example17 "
+ "concatenate "
+ "strings "
+ "just like that");
+}
+
+// Strings have single-quote or double-quote for delimiters with no
+// actual difference between the two. The given flexibility can be good
+// to avoid the need to escape content that matches the delimiter being
+// used. For example, double-quotes of HTML attributes if the string
+// contains HTML content.
+example18() {
+ print('Example18 <a href="etc">'
+ "Don't can't I'm Etc"
+ '</a>');
+}
+
+// Strings with triple single-quotes or triple double-quotes span
+// multiple lines and include line delimiters.
+example19() {
+ print('''Example19 <a href="etc">
+Example19 Don't can't I'm Etc
+Example19 </a>''');
+}
+
+// Strings have the nice interpolation feature with the $ character.
+// With $ { [expression] }, the return of the expression is interpolated.
+// $ followed by a variable name interpolates the content of that variable.
+// $ can be escaped like so \$ to just add it to the string instead.
+example20() {
+ var s1 = "'\${s}'", s2 = "'\$s'";
+ print("Example20 \$ interpolation ${s1} or $s2 works.");
+}
+
+// Optional types allow for the annotation of APIs and come to the aid of
+// IDEs so the IDEs can better refactor, auto-complete and check for
+// errors. So far we haven't declared any types and the programs have
+// worked just fine. In fact, types are disregarded during runtime.
+// Types can even be wrong and the program will still be given the
+// benefit of the doubt and be run as though the types didn't matter.
+// There's a runtime parameter that checks for type errors which is
+// the checked mode, which is said to be useful during development time,
+// but which is also slower because of the extra checking and is thus
+// avoided during deployment runtime.
+class Example21 {
+ List<String> _names;
+ Example21() {
+ _names = ["a", "b"];
+ }
+ List<String> get names => _names;
+ set names(List<String> list) {
+ _names = list;
+ }
+ int get length => _names.length;
+ void add(String name) {
+ _names.add(name);
+ }
+}
+void example21() {
+ Example21 o = new Example21();
+ o.add("c");
+ print("Example21 names '${o.names}' and length '${o.length}'");
+ o.names = ["d", "e"];
+ print("Example21 names '${o.names}' and length '${o.length}'");
+}
+
+// Class inheritance takes the form of class name extends AnotherClassName {}.
+class Example22A {
+ var _name = "Some Name!";
+ get name => _name;
+}
+class Example22B extends Example22A {}
+example22() {
+ var o = new Example22B();
+ print("Example22 class inheritance '${o.name}'");
+}
+
+// Class mixin is also available, and takes the form of
+// class name extends SomeClass with AnotherClassName {}.
+// It's necessary to extend some class to be able to mixin another one.
+// The template class of mixin cannot at the moment have a constructor.
+// Mixin is mostly used to share methods with distant classes, so the
+// single inheritance doesn't get in the way of reusable code.
+// Mixins follow the "with" statement during the class declaration.
+class Example23A {}
+class Example23Utils {
+ addTwo(n1, n2) {
+ return n1 + n2;
+ }
+}
+class Example23B extends Example23A with Example23Utils {
+ addThree(n1, n2, n3) {
+ return addTwo(n1, n2) + n3;
+ }
+}
+example23() {
+ var o = new Example23B(), r1 = o.addThree(1, 2, 3),
+ r2 = o.addTwo(1, 2);
+ print("Example23 addThree(1, 2, 3) results in '${r1}'");
+ print("Example23 addTwo(1, 2) results in '${r2}'");
+}
+
+// The Class constructor method uses the same name of the class and
+// takes the form of SomeClass() : super() {}, where the ": super()"
+// part is optional and it's used to delegate constant parameters to the
+// super-parent's constructor.
+class Example24A {
+ var _value;
+ Example24A({value: "someValue"}) {
+ _value = value;
+ }
+ get value => _value;
+}
+class Example24B extends Example24A {
+ Example24B({value: "someOtherValue"}) : super(value: value);
+}
+example24() {
+ var o1 = new Example24B(),
+ o2 = new Example24B(value: "evenMore");
+ print("Example24 calling super during constructor '${o1.value}'");
+ print("Example24 calling super during constructor '${o2.value}'");
+}
+
+// There's a shortcut to set constructor parameters in case of simpler classes.
+// Just use the this.parameterName prefix and it will set the parameter on
+// an instance variable of same name.
+class Example25 {
+ var value, anotherValue;
+ Example25({this.value, this.anotherValue});
+}
+example25() {
+ var o = new Example25(value: "a", anotherValue: "b");
+ print("Example25 shortcut for constructor '${o.value}' and "
+ "'${o.anotherValue}'");
+}
+
+// Named parameters are available when declared between {}.
+// Parameter order can be optional when declared between {}.
+// Parameters can be made optional when declared between [].
+example26() {
+ var _name, _surname, _email;
+ setConfig1({name, surname}) {
+ _name = name;
+ _surname = surname;
+ }
+ setConfig2(name, [surname, email]) {
+ _name = name;
+ _surname = surname;
+ _email = email;
+ }
+ setConfig1(surname: "Doe", name: "John");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+ setConfig2("Mary", "Jane");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+}
+
+// Variables declared with final can only be set once.
+// In case of classes, final instance variables can be set via constant
+// constructor parameter.
+class Example27 {
+ final color1, color2;
+ // A little flexibility to set final instance variables with syntax
+ // that follows the :
+ Example27({this.color1, color2}) : color2 = color2;
+}
+example27() {
+ final color = "orange", o = new Example27(color1: "lilac", color2: "white");
+ print("Example27 color is '${color}'");
+ print("Example27 color is '${o.color1}' and '${o.color2}'");
+}
+
+// To import a library, use import "libraryPath" or if it's a core library,
+// import "dart:libraryName". There's also the "pub" package management with
+// its own convention of import "package:packageName".
+// See import "dart:collection"; at the top. Imports must come before
+// other code declarations. IterableBase comes from dart:collection.
+class Example28 extends IterableBase {
+ var names;
+ Example28() {
+ names = ["a", "b"];
+ }
+ get iterator => names.iterator;
+}
+example28() {
+ var o = new Example28();
+ o.forEach((name) => print("Example28 '${name}'"));
+}
+
+// For control flow we have:
+// * standard switch with must break statements
+// * if-else if-else and ternary ..?..:.. operator
+// * closures and anonymous functions
+// * break, continue and return statements
+example29() {
+ var v = true ? 30 : 60;
+ switch (v) {
+ case 30:
+ print("Example29 switch statement");
+ break;
+ }
+ if (v < 30) {
+ } else if (v > 30) {
+ } else {
+ print("Example29 if-else statement");
+ }
+ callItForMe(fn()) {
+ return fn();
+ }
+ rand() {
+ v = new DM.Random().nextInt(50);
+ return v;
+ }
+ while (true) {
+ print("Example29 callItForMe(rand) '${callItForMe(rand)}'");
+ if (v != 30) {
+ break;
+ } else {
+ continue;
+ }
+ // Never gets here.
+ }
+}
+
+// Parse int, convert double to int, or just keep int when dividing numbers
+// by using the ~/ operation. Let's play a guess game too.
+example30() {
+ var gn, tooHigh = false,
+ n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0;
+ top = top ~/ 6;
+ gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive
+ print("Example30 Guess a number between 0 and ${top}");
+ guessNumber(i) {
+ if (n == gn) {
+ print("Example30 Guessed right! The number is ${gn}");
+ } else {
+ tooHigh = n > gn;
+ print("Example30 Number ${n} is too "
+ "${tooHigh ? 'high' : 'low'}. Try again");
+ }
+ return n == gn;
+ }
+ n = (top - bottom) ~/ 2;
+ while (!guessNumber(n)) {
+ if (tooHigh) {
+ top = n - 1;
+ } else {
+ bottom = n + 1;
+ }
+ n = bottom + ((top - bottom) ~/ 2);
+ }
+}
+
+// Programs have only one entry point in the main function.
+// Nothing is expected to be executed on the outer scope before a program
+// starts running with what's in its main function.
+// This helps with faster loading and even lazily loading of just what
+// the program needs to startup with.
+main() {
+ print("Learn Dart in 15 minutes!");
+ [example1, example2, example3, example4, example5, example6, example7,
+ example8, example9, example10, example11, example12, example13, example14,
+ example15, example16, example17, example18, example19, example20,
+ example21, example22, example23, example24, example25, example26,
+ example27, example28, example29, example30
+ ].forEach((ef) => ef());
+}
+
+```
+
+## Further Reading
+
+Dart has a comprehenshive web-site. It covers API reference, tutorials, articles and more, including a
+useful Try Dart online.
+http://www.dartlang.org/
+http://try.dartlang.org/
+
+
+
diff --git a/fsharp.html.markdown b/fsharp.html.markdown
new file mode 100644
index 00000000..5c54130d
--- /dev/null
+++ b/fsharp.html.markdown
@@ -0,0 +1,431 @@
+---
+language: F#
+author: Scott Wlaschin
+author_url: http://fsharpforfunandprofit.com/
+---
+
+F# is a general purpose functional/OO programming language. It's free and open source, and runs on Linux, Mac, Windows and more.
+
+It has a powerful type system that traps many errors at compile time, but it uses type inference so that it read more like a dynamic language.
+
+The syntax of F# is similar to Python:
+
+* Curly braces are not used to delimit blocks of code. Instead, indentation is used.
+* Whitespace is used to separate parameters rather than commas.
+
+If you want to try out the code below, you can go to [tryfsharp.org](http://www.tryfsharp.org/Create) and paste it into an interactive REPL.
+
+```csharp
+
+// single line comments use a double slash
+(* multi line comments use (* . . . *) pair
+
+-end of multi line comment- *)
+
+// ================================================
+// Basic Syntax
+// ================================================
+
+// ------ "Variables" (but not really) ------
+// The "let" keyword defines an (immutable) value
+let myInt = 5
+let myFloat = 3.14
+let myString = "hello" //note that no types needed
+
+// ------ Lists ------
+let twoToFive = [2;3;4;5] // Square brackets create a list with
+ // semicolon delimiters.
+let oneToFive = 1 :: twoToFive // :: creates list with new 1st element
+// The result is [1;2;3;4;5]
+let zeroToFive = [0;1] @ twoToFive // @ concats two lists
+
+// IMPORTANT: commas are never used as delimiters, only semicolons!
+
+// ------ Functions ------
+// The "let" keyword also defines a named function.
+let square x = x * x // Note that no parens are used.
+square 3 // Now run the function. Again, no parens.
+
+let add x y = x + y // don't use add (x,y)! It means something
+ // completely different.
+add 2 3 // Now run the function.
+
+// to define a multiline function, just use indents. No semicolons needed.
+let evens list =
+ let isEven x = x%2 = 0 // Define "isEven" as a sub function
+ List.filter isEven list // List.filter is a library function
+ // with two parameters: a boolean function
+ // and a list to work on
+
+evens oneToFive // Now run the function
+
+// You can use parens to clarify precedence. In this example,
+// do "map" first, with two args, then do "sum" on the result.
+// Without the parens, "List.map" would be passed as an arg to List.sum
+let sumOfSquaresTo100 =
+ List.sum ( List.map square [1..100] )
+
+// You can pipe the output of one operation to the next using "|>"
+// Piping data around is very common in F#, similar to UNIX pipes.
+
+// Here is the same sumOfSquares function written using pipes
+let sumOfSquaresTo100piped =
+ [1..100] |> List.map square |> List.sum // "square" was defined earlier
+
+// you can define lambdas (anonymous functions) using the "fun" keyword
+let sumOfSquaresTo100withFun =
+ [1..100] |> List.map (fun x -> x*x) |> List.sum
+
+// In F# there is no "return" keyword. A function always
+// returns the value of the last expression used.
+
+// ------ Pattern Matching ------
+// Match..with.. is a supercharged case/switch statement.
+let simplePatternMatch =
+ let x = "a"
+ match x with
+ | "a" -> printfn "x is a"
+ | "b" -> printfn "x is b"
+ | _ -> printfn "x is something else" // underscore matches anything
+
+// F# doesn't allow nulls by default -- you must use an Option type
+// and then pattern match.
+// Some(..) and None are roughly analogous to Nullable wrappers
+let validValue = Some(99)
+let invalidValue = None
+
+// In this example, match..with matches the "Some" and the "None",
+// and also unpacks the value in the "Some" at the same time.
+let optionPatternMatch input =
+ match input with
+ | Some i -> printfn "input is an int=%d" i
+ | None -> printfn "input is missing"
+
+optionPatternMatch validValue
+optionPatternMatch invalidValue
+
+// ------ Printing ------
+// The printf/printfn functions are similar to the
+// Console.Write/WriteLine functions in C#.
+printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
+printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
+
+// There are also sprintf/sprintfn functions for formatting data
+// into a string, similar to String.Format in C#.
+
+// ================================================
+// More on functions
+// ================================================
+
+// F# is a true functional language -- functions are first
+// class entities and can be combined easy to make powerful
+// constructs
+
+// Modules are used to group functions together
+// Indentation is needed for each nested module.
+module Addition =
+
+ // define a simple adding function
+ let add x y = x + y
+
+ // basic usage of a function
+ let a = add 1 2
+ printfn "1+2 = %i" a
+
+ // partial application
+ let add42 = add 42
+ let b = add42 1
+ printfn "42+1 = %i" b
+
+ // composition
+ let add1 = add 1
+ let add2 = add 2
+ let add3 = add1 >> add2
+ let c = add3 7
+ printfn "3+7 = %i" c
+
+ // higher order functions
+ [1..10] |> List.map add3 |> printfn "new list is %A"
+
+ // lists of functions, and more
+ let add6 = [add1; add2; add3] |> List.reduce (>>)
+ let d = add6 7
+ printfn "1+2+3+7 = %i" d
+
+// ================================================
+// Data Types
+// ================================================
+
+
+module DataTypeExamples =
+
+ // All data is immutable by default
+
+ // Tuples are quick 'n easy anonymous types
+ let twoTuple = 1,2
+ let threeTuple = "a",2,true
+
+ // Record types have named fields
+ type Person = {First:string; Last:string}
+ let person1 = {First="john"; Last="Doe"}
+
+ // Union types (aka variants) have a set of choices
+ // Only case can be valid at a time.
+ type Temp =
+ | DegreesC of float
+ | DegreesF of float
+ let temp1 = DegreesF 98.6
+ let temp2 = DegreesC 37.0
+
+ // Union types are great for modelling state without using flags
+ type EmailAddress =
+ | ValidEmailAddress of string
+ | InvalidEmailAddress of string
+
+ let trySendEmail email =
+ match email with // use pattern matching
+ | ValidEmailAddress address -> () // send
+ | InvalidEmailAddress address -> () // dont send
+
+ // Types can be combined recursively in complex ways
+ // without having to create subclasses
+ type Employee =
+ | Worker of Person
+ | Manager of Employee list
+
+ let jdoe = {First="John";Last="Doe"}
+ let worker = Worker jdoe
+
+ // The combination of union types and record types together
+ // provide a great foundation for domain driven design.
+ // You can create hundreds of little types that accurately
+ // reflect the domain.
+
+ type CartItem = { ProductCode: string; Qty: int }
+ type Payment = Payment of float
+ type ActiveCartData = { UnpaidItems: CartItem list }
+ type PaidCartData = { PaidItems: CartItem list; Payment: Payment}
+
+ type ShoppingCart =
+ | EmptyCart // no data
+ | ActiveCart of ActiveCartData
+ | PaidCart of PaidCartData
+
+ // All complex types have pretty printing built in for free
+ printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
+ twoTuple person1 temp1 worker
+
+// ================================================
+// Active patterns
+// ================================================
+
+module ActivePatternExamples =
+
+ // F# has a special type of pattern matching called "active patterns"
+ // where the pattern can be parsed or detected dynamically.
+
+ // for example, define an "active" pattern to match character types...
+ let (|Digit|Letter|Whitespace|Other|) ch =
+ if System.Char.IsDigit(ch) then Digit
+ else if System.Char.IsLetter(ch) then Letter
+ else if System.Char.IsWhiteSpace(ch) then Whitespace
+ else Other
+
+ // ... and then use it to make parsing logic much clearer
+ let printChar ch =
+ match ch with
+ | Digit -> printfn "%c is a Digit" ch
+ | Letter -> printfn "%c is a Letter" ch
+ | Whitespace -> printfn "%c is a Whitespace" ch
+ | _ -> printfn "%c is something else" ch
+
+ // print a list
+ ['a';'b';'1';' ';'-';'c'] |> List.iter printChar
+
+
+// ================================================
+// Conciseness
+// ================================================
+
+module AlgorithmExamples =
+
+ // F# has a high signal/noise ratio, so code reads
+ // almost like the actual algorithm
+
+ // ------ Example: define sumOfSquares function ------
+ let sumOfSquares n =
+ [1..n] // 1) take all the numbers from 1 to n
+ |> List.map square // 2) square each one
+ |> List.sum // 3) sum the results
+
+ // test
+ sumOfSquares 100 |> printfn "Sum of squares = %A"
+
+ // ------ Example: define a sort function ------
+ let rec sort list =
+ match list with
+ // If the list is empty
+ | [] ->
+ [] // return an empty list
+ // If the list is not empty
+ | firstElem::otherElements -> // take the first element
+ let smallerElements = // extract the smaller elements
+ otherElements // from the remaining ones
+ |> List.filter (fun e -> e < firstElem)
+ |> sort // and sort them
+ let largerElements = // extract the larger ones
+ otherElements // from the remaining ones
+ |> List.filter (fun e -> e >= firstElem)
+ |> sort // and sort them
+ // Combine the 3 parts into a new list and return it
+ List.concat [smallerElements; [firstElem]; largerElements]
+
+ // test
+ sort [1;5;23;18;9;1;3] |> printfn "Sorted = %A"
+
+// ================================================
+// Asynchronous Code
+// ================================================
+
+module AsyncExample =
+
+ // F# has some built-in features to help with async code
+ // without encountering the "pyramid of doom"
+ //
+ // The following example downloads a set of web pages in parallel.
+
+ open System.Net
+ open System
+ open System.IO
+ open Microsoft.FSharp.Control.CommonExtensions
+
+ // Fetch the contents of a URL asynchronously
+ let fetchUrlAsync url =
+ async {
+ let req = WebRequest.Create(Uri(url))
+ use! resp = req.AsyncGetResponse()
+ use stream = resp.GetResponseStream()
+ use reader = new IO.StreamReader(stream)
+ let html = reader.ReadToEnd()
+ printfn "finished downloading %s" url
+ }
+
+ // a list of sites to fetch
+ let sites = ["http://www.bing.com";
+ "http://www.google.com";
+ "http://www.microsoft.com";
+ "http://www.amazon.com";
+ "http://www.yahoo.com"]
+
+ // do it
+ sites
+ |> List.map fetchUrlAsync // make a list of async tasks
+ |> Async.Parallel // set up the tasks to run in parallel
+ |> Async.RunSynchronously // start them off
+
+// ================================================
+// .NET compatability
+// ================================================
+
+module NetCompatibilityExamples =
+
+ // F# can do almost everything C# can do, and it integrates
+ // seamlessly with .NET or Mono libraries.
+
+ // ------- work with existing library functions -------
+
+ let (i1success,i1) = System.Int32.TryParse("123");
+ if i1success then printfn "parsed as %i" i1 else printfn "parse failed"
+
+ // ------- Implement interfaces on the fly! -------
+
+ // create a new object that implements IDisposable
+ let makeResource name =
+ { new System.IDisposable
+ with member this.Dispose() = printfn "%s disposed" name }
+
+ let useAndDisposeResources =
+ use r1 = makeResource "first resource"
+ printfn "using first resource"
+ for i in [1..3] do
+ let resourceName = sprintf "\tinner resource %d" i
+ use temp = makeResource resourceName
+ printfn "\tdo something with %s" resourceName
+ use r2 = makeResource "second resource"
+ printfn "using second resource"
+ printfn "done."
+
+ // ------- Object oriented code -------
+
+ // F# is also a fully fledged OO language.
+ // It supports classes, inheritance, virtual methods, etc.
+
+ // interface
+ type IEnumerator<'a> =
+ abstract member Current : 'a
+ abstract MoveNext : unit -> bool
+
+ // abstract base class with virtual methods
+ [<AbstractClass>]
+ type Shape() =
+ //readonly properties
+ abstract member Width : int with get
+ abstract member Height : int with get
+ //non-virtual method
+ member this.BoundingArea = this.Height * this.Width
+ //virtual method with base implementation
+ abstract member Print : unit -> unit
+ default this.Print () = printfn "I'm a shape"
+
+ // concrete class that inherits from base class and overrides
+ type Rectangle(x:int, y:int) =
+ inherit Shape()
+ override this.Width = x
+ override this.Height = y
+ override this.Print () = printfn "I'm a Rectangle"
+
+ //test
+ let r = Rectangle(2,3)
+ printfn "The width is %i" r.Width
+ printfn "The area is %i" r.BoundingArea
+ r.Print()
+
+ // ------- extension methods -------
+
+ //Just as in C#, F# can extend existing classes with extension methods.
+ type System.String with
+ member this.StartsWithA = this.StartsWith "A"
+
+ //test
+ let s = "Alice"
+ printfn "'%s' starts with an 'A' = %A" s s.StartsWithA
+
+ // ------- events -------
+
+ type MyButton() =
+ let clickEvent = new Event<_>()
+
+ [<CLIEvent>]
+ member this.OnClick = clickEvent.Publish
+
+ member this.TestEvent(arg) =
+ clickEvent.Trigger(this, arg)
+
+ // test
+ let myButton = new MyButton()
+ myButton.OnClick.Add(fun (sender, arg) ->
+ printfn "Click event with arg=%O" arg)
+
+ myButton.TestEvent("Hello World!")
+
+```
+
+## More Information
+
+For more demonstrations of F#, go to the [Try F#](http://www.tryfsharp.org/Learn) site, or my [why use F#](http://fsharpforfunandprofit.com/why-use-fsharp/) series.
+
+Read more about F# at [fsharp.org](http://fsharp.org/).
+
+
+
+
diff --git a/haskell.html.markdown b/haskell.html.markdown
index a5a6117f..563674c9 100644
--- a/haskell.html.markdown
+++ b/haskell.html.markdown
@@ -89,7 +89,8 @@ last [1..5] -- 5
-- with a conditional
[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
--- Every element in a tuple can be a different type, but a tuple has a fixed length.
+-- Every element in a tuple can be a different type, but a tuple has a
+-- fixed length.
-- A tuple:
("haskell", 1)
@@ -106,11 +107,13 @@ add a b = a + b
-- Using the function
add 1 2 -- 3
--- You can also put the function name between the two arguments with backticks:
+-- You can also put the function name between the two arguments
+-- with backticks:
1 `add` 2 -- 3
--- You can also define functions that have no characters! This lets you define
--- your own operators! Here's an operator that does integer division
+-- You can also define functions that have no characters! This lets
+-- you define your own operators! Here's an operator that does
+-- integer division
(//) a b = a `div` b
35 // 4 -- 8
@@ -135,12 +138,13 @@ foo (x, y) = (x + 1, y + 2)
map func [x] = [func x]
map func (x:xs) = func x:(map func xs)
--- Anonymous functions are created with a backslash followed by all the arguments.
+-- Anonymous functions are created with a backslash followed by
+-- all the arguments.
map (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
--- using fold (called `inject` in some languages) with an anonymous function.
--- foldl1 means fold left, and use the first value in the array as the initial
--- value for the accumulator.
+-- using fold (called `inject` in some languages) with an anonymous
+-- function. foldl1 means fold left, and use the first value in the
+-- array as the initial value for the accumulator.
foldl1 (\acc x -> acc + x) [1..5] -- 15
----------------------------------------------------
@@ -210,7 +214,7 @@ haskell = if 1 == 1
then "awesome"
else "awful"
--- case statements: Here's how you could parse command line arguments in Haskell
+-- case statements: Here's how you could parse command line arguments
case args of
"help" -> printHelp
"start" -> startProgram
@@ -280,3 +284,6 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
```
Haskell is easy to install. Get it [here](http://www.haskell.org/platform/).
+
+You can find a much gentler introduction from the excellent [Learn you a Haskell](http://learnyouahaskell.com/)
+