{"id":19,"date":"2008-10-26T19:23:09","date_gmt":"2008-10-26T18:23:09","guid":{"rendered":"http:\/\/www.leading-edge-dev.de\/?p=19"},"modified":"2008-10-27T09:28:51","modified_gmt":"2008-10-27T08:28:51","slug":"ein-blick-auf-f","status":"publish","type":"post","link":"https:\/\/www.minddriven.de\/index.php\/technology\/dot-net\/ein-blick-auf-f","title":{"rendered":"Ein Blick auf F#"},"content":{"rendered":"<p>Funktionale Programmierung hat mich bereits w\u00e4hrend des Studiums besch\u00e4ftigt, allerdings eher am Rande in Lehrveranstaltungen wie &#8222;Objektorientierte Konzepte&#8220;, wo in den \u00dcbungen <a href=\"http:\/\/de.wikipedia.org\/wiki\/Haskell_(Programmiersprache)\">Haskell<\/a> gepredigt wurde. Teils verwirrt, teils fasziniert von dieser Art zu denken und zu programmieren hat mich das Thema nie richtig losgelassen und erlebt gerade einen pers\u00f6nlichen Aufschwung durch F#. F# ist Microsoft&#8217;s funktionale .NET Programmiersprache, die wie viele Innovationen Microsoft Research entsprungen ist. Es ist explizit hervorzuheben, dass F# das .NET-Framework als Basis nutzt. Demzufolge stehen auch alle Bibliotheken zur Verf\u00fcgung, welche .NET so m\u00e4chtig machen. Doch genug der Vorrede, los geht es mit F#. Ein kleiner Praxistest soll an dieser Stelle erste Eindr\u00fccke vermitteln&#8230;<\/p>\n<h2>Los geht&#8217;s&#8230;<\/h2>\n<p>Die aktuelle F# CTP kann auf der zugeh\u00f6rigen <a href=\"http:\/\/msdn.microsoft.com\/de-de\/fsharp\/default(en-us).aspx\">MSDN-Seite<\/a> herunter geladen werden. Hier stehen auch\u00a0weitere Ressourcen zur Verf\u00fcgung, die beim Einstieg in die neue Programmiersprache behilflich sind. Flux installiert\u00a0l\u00e4sst sich\u00a0im Visual Studio bei der Erstellung eines neuen Projekts der Punkt &#8222;Visual F#&#8220; w\u00e4hlen. Die ersten Zeilen Code sind bekanntlich die schwersten in jeder Programmiersprache, und doch halfen mir bereits hier meine ersten Erfahrungen in Haskell. Der gro\u00dfe Unterschied: F# ist keine rein funktionale Programmiersprache wie Haskell, sie enth\u00e4lt ebenfalls imperative Elemente, welche die Ausdruckf\u00e4higkeit an einigen Stellen vereinfachen sollen. Erste Schritte waren also schnell gemacht. Mit &#8222;let&#8220; werden Variablen deklariert und definiert, wobei es sich hierbei auch um Funktionen handeln darf. &#8222;let twice x = 2*x&#8220; erzeugt z.B. eine Funktion &#8222;twice&#8220;, welche die Signatur &#8222;int -&gt; int&#8220; besitzt und zu einem \u00fcbergebenen Argument seinen zweifachen Wert zur\u00fcckgibt. Diese Funktion darf wieder an weitere Funktionen \u00fcbergeben werden, Funktionen h\u00f6herer Ordnung sind also ohne Probleme m\u00f6glich. F# inferiert dabei den Typ von Variablen, d.h. ihre Signatur wird aus den\u00a0angegebenen Definitionen automatisch ermittelt und so z.B. auch bei der Fehlerpr\u00fcfung verwendet. Als Beispiel f\u00fcr eine Signatur sei &#8222;List.map&#8220; angegeben. Deren Signatur lautet: &#8222;val map: (&#8218;a -&gt; &#8218;b) -&gt; &#8218;a list -&gt;\u00a0&#8218;b list&#8220;. What the heck? Eigentlich ist es ganz einfach. &#8222;-&gt;&#8220; gibt jeweils die Abgrenzung zweier Parameter an. Der Ausdruck nach dem letzten &#8222;-&gt;&#8220; stellt den R\u00fcckgabetyp dar. Nehmen wir C# als Hilfestellung und schauen uns die Methode &#8222;Math.Pow&#8220; an, so hat diese in C# die Signatur &#8222;double Pow(double x, double y)&#8220; und \u00fcbersetzt auf unser Schema die Signatur &#8222;double -&gt; double -&gt; double&#8220;. Sie w\u00fcrde also 2 double-Werte als Argumente nehmen und einen double-Wert zur\u00fcckliefern. Aber zur\u00fcck zu List.map&#8230; (&#8218;a -&gt; &#8218;b) besagt: &#8222;das erste Argument der Funktion List.map ist eine Funktion, welche ein Element des Typs a entgegennimmt und ein Element des Typs b zur\u00fcckliefert&#8220;. Das zweite Argument &#8222;&#8218;a list&#8220; besagt, dass eine Liste mit Elementen vom Typ a erwartet wird. Der R\u00fcckgabetyp von List.map ist &#8218;b list, was als letzter Term der Signatur ausgewiesen ist. Was macht List.map jetzt eigentlich? Es &#8222;mapped&#8220; Elemente einer \u00fcbergebenen Liste mit Hilfe einer ebenfalls als Parameter \u00fcbergebenen Funktion. Dazu wird auf jedes Listenelement des Typs a die Funktion angewendet, welche ein Element des Typs b zur\u00fcckliefert. Am Ende ergibt dies eine Liste von Elementen des Typs b, welche zur\u00fcckgegeben wird. Auch Lambda-Ausdr\u00fccke sind in F# kein Problem. &#8222;List.map (fun x -&gt; 2*x) numbers&#8220; w\u00fcrde z.B. von allen Elementen der Liste &#8222;numbers&#8220; den doppelten Wert erzeugen und dies als Liste zur\u00fcckliefern. Klar erkennbar sind bereits hier u.a. das funktionale Paradigma, Typsicherheit und\u00a0Polymorphismus, auch wird bereits hier die Ausdrucksm\u00e4chtigkeit erkennbar, wenn man bereit ist sich auf funktionale Programmierung einzulassen&#8230;<\/p>\n<h2>Quicksort in F#<\/h2>\n<p>Beim St\u00f6bern bin ich auf eine F#-Implementierung des Sortieralgorithmus Quicksort gesto\u00dfen, welche ich euch nicht vorenthalten wollte:<\/p>\n<pre class=\"ocaml ocaml\" style=\"FONT-FAMILY: monospace\"><span style=\"font-weight: bold; color: #00060c;\">let<\/span> lt  x <span style=\"color: #a52a2a;\">=<\/span> <span style=\"font-weight: bold; color: #00060c;\">List<\/span><span style=\"color: #a52a2a;\">.<\/span><span style=\"color: #000600;\">filter<\/span> <span style=\"color: #060c06;\">(<\/span><span style=\"font-weight: bold; color: #00060c;\">fun<\/span> xi <span style=\"color: #a52a2a;\">-&gt;<\/span> xi <span style=\"color: #a52a2a;\">&lt;<\/span> x<span style=\"color: #060c06;\">)<\/span>\r\n<span style=\"font-weight: bold; color: #00060c;\">let<\/span> geq x <span style=\"color: #a52a2a;\">=<\/span> <span style=\"font-weight: bold; color: #00060c;\">List<\/span><span style=\"color: #a52a2a;\">.<\/span><span style=\"color: #000600;\">filter<\/span> <span style=\"color: #060c06;\">(<\/span><span style=\"font-weight: bold; color: #00060c;\">fun<\/span> xi <span style=\"color: #a52a2a;\">-&gt;<\/span> xi <span style=\"color: #a52a2a;\">&gt;=<\/span> x<span style=\"color: #060c06;\">)<\/span>\r\n\u00a0\r\n<span style=\"font-weight: bold; color: #00060c;\">let<\/span> <span style=\"font-weight: bold; color: #00060c;\">rec<\/span> qs <span style=\"color: #a52a2a;\">=<\/span> <span style=\"font-weight: bold; color: #00060c;\">function<\/span>\r\n             | <span style=\"color: #060c06;\">[<\/span><span style=\"color: #060c06;\">]<\/span>    <span style=\"color: #a52a2a;\">-&gt;<\/span> <span style=\"color: #060c06;\">[<\/span><span style=\"color: #060c06;\">]<\/span>\r\n             | x<span style=\"color: #a52a2a;\">::<\/span>xs <span style=\"color: #a52a2a;\">-&gt;<\/span> <span style=\"color: #060c06;\">(<\/span>xs |&gt; <span style=\"color: #060c06;\">(<\/span>lt x <span style=\"color: #a52a2a;\">&gt;&gt;<\/span> qs<span style=\"color: #060c06;\">)<\/span><span style=\"color: #060c06;\">)<\/span> @ <span style=\"color: #060c06;\">[<\/span>x<span style=\"color: #060c06;\">]<\/span> @ <span style=\"color: #060c06;\">(<\/span>xs |&gt; <span style=\"color: #060c06;\">(<\/span>geq x <span style=\"color: #a52a2a;\">&gt;&gt;<\/span> qs<span style=\"color: #060c06;\">)<\/span><span style=\"color: #060c06;\">)<\/span><\/pre>\n<p>That&#8217;s it&#8230; \u00dcber z.B. &#8222;<span style=\"font-size: x-small;\">printfn <\/span><span style=\"font-size: x-small; color: #800000;\"><span style=\"font-size: x-small; color: #800000;\">&#8222;sorted: %A&#8220;<\/span><\/span><span style=\"font-size: x-small;\"> (qs [3;1;9;5;2;10;8;6;7;4])<\/span>&#8220; kann die Sortierung getestet werden.\u00a0Zun\u00e4chst werden zwei\u00a0Funktionen &#8222;lt&#8220; und &#8222;geq&#8220; definiert, welche jeweils eine Element x \u00fcbergeben bekommen. Sie liefern genau die <em>Funktionen<\/em> zur\u00fcck, welche f\u00fcr einen weiteren \u00fcbergebenen\u00a0Wert xi berechnen, ob x kleiner oder gr\u00f6\u00dfer gleich xi ist. &#8222;let rec qs &#8230;&#8220; definiert eine rekursive Funktion qs, welche eine Liste als Argument \u00fcbergeben bekommt. Mit &#8222;|&#8220; wird der Wert der Liste gepr\u00fcft und anhand dessen der Funktionswert bestimmt. Ist die Liste leer (&#8222;[ ]&#8220;), so wird auch nur eine leere Liste zur\u00fcckgeliefert. Ansonsten wird die Argumentliste mittels &#8222;x::xs&#8220; in den Kopf x und die Restliste xs zerlegt und mit diesen beiden Elementen wird der folgende Term definiert. Dieser ist zun\u00e4chst in 2 Teile aufgeteilt, die mit &#8222;@&#8220; voneinander getrennt sind. Im mittleren steht mit [x] eine Einerliste, welche nur das Pivotelement des Quicksort-Durchlaufs enth\u00e4lt. Links davon wird die Teilliste von xs erzeugt, welche alle Elemente kleiner als x enth\u00e4lt, rechts davon entsprechend die Teilliste mit allen Elementen gr\u00f6\u00dfer gleich xs. Mit &#8222;<span style=\"color: #060c06;\">(<\/span>xs |&gt; <span style=\"color: #060c06;\">(<\/span>lt x <span style=\"color: #a52a2a;\">&gt;&gt;<\/span> qs<span style=\"color: #060c06;\">)<\/span><span style=\"color: #060c06;\">)<\/span>&#8220; werden \u00fcber den Pipe-Operator |&gt; die Elemente aus xs ausgew\u00e4hlt, die kleiner als x sind (die Liste xs wird mittels Pipe weitergeleitet an lt und qs) und f\u00fcr diese Teilliste wird qs rekursiv aufgerufen (&gt;&gt; stellt die Verkettung zweier Funktionsaufrufe dar). Da mit jedem Aufruf von qs die Liste um mind. 1 Element kleiner wird, terminiert der Algorithmus in endlich vielen Schritten. Ok, an die Syntax muss man sich erst einmal gew\u00f6hnen, aber mal ehrlich&#8230; wie viele Zeilen h\u00e4ttet ihr in C# gebraucht?<\/p>\n<h2>Ja und?<\/h2>\n<p>Jetzt k\u00f6nnte man sagen: ja fein, F# ist eine neue funktionale Programmiersprache, hat das .NET Framework unter sich liegen und l\u00e4sst sich auch recht flexibel verwenden&#8230; doch warum in aller Welt sollte mich das k\u00fcmmern? Funktionale Programmiersprachen gibt es schon seit Ewigkeiten und mit C# komme ich gut zurecht, was will ich mit F#? Die Antwort auf diese Frage ist nicht leicht und zudem recht komplex. Zun\u00e4chst einmal gibt es derzeit keine sehr guten Gr\u00fcnde, um F# wirklich intensiv zu lernen. Im Arbeitsleben ist diese Sprache noch nicht angelangt und somit eher eine Spielwiese zum Lernen funktionaler Programmierung und zum Erfreuen von enthusiastischen Programmierern. Es ist nicht abzusehen und auch nicht das Ziel von Microsoft, dass F# bestehende Sprachen wie C# abl\u00f6st. Ein gro\u00dfer Aspekt f\u00fcr die funktionale Programmierung ist das Problem der parallelen Programmierung. Viele Jahrzehnte lang haben wir sequentiell programmiert und imperative Programmiersprachen eigneten sich hierzu hervorragend. Doch mit dem Aufkommen von Multicore-Prozessoren wird die Notwendigkeit nach der Parallelisierung von Aufgaben immer gr\u00f6\u00dfer und hier sto\u00dfen imperative Programmiersprachen an ihre Grenzen. Funktionale Programmiersprachen hingegen sind zun\u00e4chst nebenwirkungsfrei und damit grundlegend f\u00fcr eine Parallelisierung geeignet. Variablen sind immutable (unver\u00e4nderlich), womit Programmteile ohne Probleme verteilt bearbeitet werden k\u00f6nnen. Funktionale Programmierung kann damit einen Ausweg aus dem Dilemma der Parallelisierung von Programmen weisen. Wichtig dabei ist meiner Meinung nach, dass kein kompletter Paradigmenwechsel vollzogen wird. Funktionale Programmierung ist schwer und teilweise kompliziert, wenn man lange Zeit imperativ programmiert hat. Imperative Programmiersprachen geben einem Programmierer mehr Flexibilit\u00e4t mit dem Nachteil, dass es Wechselwirkungen geben kann, was gerade bei komplexen Softwareanwendungen h\u00e4ufig zu erheblichen Problemen f\u00fchrt. Aber funktionale Elemente werden meiner Meinung nach Einzug in Sprachen, Bibliotheken und Muster halten und somit bestehende Programmiersprachen wie C# bereichern. F# ist dabei auf einem guten Weg, da es eine hohe Ausdrucksm\u00e4chtigkeit besitzt und performanter agiert als viele seiner funktionalen Kollegen. Erste Elemente von F# sind bereits in C# eingeflossen, es bleibt abzuwarten welche noch folgen werden&#8230;<\/p>\n<p><em>So far for now&#8230; Matthias<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Funktionale Programmierung hat mich bereits w\u00e4hrend des Studiums besch\u00e4ftigt, allerdings eher am Rande in Lehrveranstaltungen wie &#8222;Objektorientierte Konzepte&#8220;, wo in den \u00dcbungen Haskell gepredigt wurde. Teils verwirrt, teils fasziniert von dieser Art zu denken und zu programmieren hat mich das Thema nie richtig losgelassen und erlebt gerade einen pers\u00f6nlichen Aufschwung durch F#. F# ist Microsoft&#8217;s &hellip; <a href=\"https:\/\/www.minddriven.de\/index.php\/technology\/dot-net\/ein-blick-auf-f\" class=\"more-link\"><span class=\"screen-reader-text\">Ein Blick auf F#<\/span> weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,35],"tags":[309,28,29,36,23,37],"class_list":["post-19","post","type-post","status-publish","format-standard","hentry","category-dot-net","category-f-sharp","tag-dot-net","tag-f--sharp","tag-funktionale-programmierung","tag-immutable","tag-parallele-programmierung","tag-quicksort"],"_links":{"self":[{"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/posts\/19","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/comments?post=19"}],"version-history":[{"count":3,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/posts\/19\/revisions"}],"predecessor-version":[{"id":23,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/posts\/19\/revisions\/23"}],"wp:attachment":[{"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/media?parent=19"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/categories?post=19"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.minddriven.de\/index.php\/wp-json\/wp\/v2\/tags?post=19"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}