F# Funktionale Programmierung Frank Adler
Was ist funktionale Programmierung Funktionale Programmierung ist die Komposition von Funktionen.
Funktionale Konzepte First-Class Functions Higher-Order Functions Pure Functions Currying und Partial Application Strong Typing Recursion Pattern Matching Lambdas Closures
Stärken der funktionalen Programmierung Berechnung, Transformation Symbolische Berechnung Keine Seiteneffekte Beweisbarkeit Asynchrone Programmierung
Geschichte 2002.Net 1.0 veröffentlicht und F# Research Projekt start F# hat seine Wurzeln in OCaml(Quasi Ocaml.Net) Gemeinsamkeiten mit Haskell(Sequence Expressions und Workflows) Enge Verbindungen zwischen den Sprachdesignern und der Community aller 3 Sprachen
F# Die aktuelle Version 3.0 erschien mit.net 4.5 Seit Anfang des Jahres unter Fsharp.org frei verfügbar Außer Windows auch unter Mono lauffähig
F# Entwicklung Visual Studio Professional aufwärts 2012 F# 3.0 2010 F# 2.0 Visual Studio Express Xamarin Studio oder MonoDevelop SharpDevelop(F# 2.0) Emacs Linqpad
Modul Jeder Funktion muss einem Modul zugeordnet werden. Wird kein Modul angegeben wird der Dateiname als Modulname verwendet Das Modul wird im.net Framework als Klasse angelegt. Methoden als statische Methoden
Einfache Datentypen Alle einfachen Datentypen die wir auch von C# kennen. z.b. byte, int, uint, float, decimal, Die Standardoperatoren +, -, *, /, **, % Funktionen abs, ceil, sin, Charund Strings
Let Variablen letx = 5 lety = 7 Funktionen letaddx y = x + y
Tupel Ein Tupel ist eine geordnete Liste mit Objekten let tuple = (1,"A", 5.4) Syntax: In Klammern mit Komma getrennt Mit fstund sndzugriff auf das 1. und 2. Element eines 2 Element Tupels Zuweisung der einzelnen Elemente des Tupels letx, y, z = tuple
if Abfrage In FSharp werden Blöcke durch einrücken gekennzeichnet (wie in Python) Jeder Zweig hat einen eigenen Rückgabewert Die Typen der Rückgabewerte des then-und des else-zweigs müssen gleich sein ifx > 5 then x -1 else x -2
Funktionen Eine Funktion hat immer einen Parameter und einen Rückgabewert Schreibweise let add x y = x + y void Funktionen gibt es nicht Funktionen ohnen Rückgabewert geben unit zurück. Diese Funktionen haben Seiteneffekte
Lambda Lambdas sind anonyme Funktionen funxy ->x + y Ein paar Regeln Einfach halten Ggfs. in ein Funktion umwandeln
Type Inference F# ist wie C# strikt typisiert. Der Compiler versucht die Typen herzuleiten. letf (a, b, c) = ifb thena(b) elsec+1;; valf : a:(bool ->int)* b:bool * c:int ->int b = boolweilalsbedingungimif c = intweil+ 1 a = FunktionmitboolParameter und intalsrückgabeweilelse Zweig auch int zurück gibt
Currying Jede Funktion hat ein Parameter und einen Rückgabewert. Wenn mehrere Parameter vorhanden sind erfolgt die Zerlegung in einzelne Funktionen f x y int-> int-> int Wird gelesen als eine Funktion mit einem intparameter und als Rückgabe eine Funktion! mit einem int Parameter und int als Rückgabe. Manchmal auch als Schönfinkeln bezeichnet.
Partial Application Aufrufen einer Funktion mit unvollständiger Parameterliste letaddx y = x + y Durch add10 wird der erste Parameter (x) auf 10 gebunden und eine Funktion mit einem Parameter (y) zurückgegeben Vorher: letadd10 = add10 x -> y -> x + y Nachher: y -> 10 + y
Recursion letrecfactorialx = ifx <= 1 then 1 else x * factorial (x 1)
Tail/ End Recursion letfactorialx = let rec tailrecfactorial x acc = ifx <= 1 then acc else tailrecfactorial (x-1)(acc* x) tailrecfactorial x 1
Mutualy Recursion letrecisoddx = if x = 0 then false elifx = 1 then true elseiseven(x -1) andisevenx = if x = 0 then true elifx = 1 then false elseisodd(x -1)
List [1;2;3] [1..10] [1..2..10] [forx in [1..5]-> x * x] List Funktionen im List Modul map, fold, Verkettete Liste Wird nach vorne erweitert
Arrays Gleiche Initialisierung wie bei den Listen Sind mutable! Funktionen im Array Modul let arr = [ 1;2;3;4;5 ] Array.sum arr Array.setarr0 8
Verschachtelte Aufrufe oder List.sum List.map (fun x -> x + 5) (List.map (funx-> x * x) [1..10])) letl1 = List.map(funx -> x * x) [1..10] letl2 = List.map (fun x -> x + 5) l1 List.sum l2
Pipe-Operatoren Pipe Forward letinline( >) x f = f x Forward composition operator let inline(>>) f g x = g(f x) Pipe Backward letinline(< ) f x = f x Backward composition operator letinline(<<) f g x = f(g x)
Pipes Pipe Forward und Forward Composition werden am häufigsten gebraucht [1..10] > List.map(funx -> x * x) > List.map (fun x -> x + 5) > List.sum (List.map(funx -> x * x) >> List.map (fun x -> x + 5) >> List.sum) [1..10]
Option type Option<'a> = Some of 'a None if x = 5 then Some(x) else None Im Modul Option gibt es einige Funktionen die mit Optionen arbeiten In Haskell ähnliches Konstrukt maybe
Records Definition type cell = { Index: int; Value: int option; Candidates : int list } member this.isset = this.value <> None Einen Record anlegen let c = { Index = 5; Value = None; Candidates = [1..9]; } Einen Record ändern (neu erstellen) let c = { c with Value = Some(3); }
Record Fakten Vereinfachte Klassen Vorteile Type Inference erkennt Records Immutable Keine Vererbung Pattern matching möglich Equality und Comparison for free
Discriminated Unions type Strategy = NakedSingle of (int * int * int) HiddenSingle of (int * int * int)
Disc. Union Fakten Ein Typ aus einer Gruppe von möglichen Typen Kleine Klassenhierarchie Der erste ist Optional
Pattern Matching matchx with true-> printf True false-> printf False matchx, y with false, false-> true _, _ -> false matchx, y with false, false-> false false, true-> true true, false-> true true, true-> false match (1,"a", 3) with 1,y,3 -> printf "3:%s" y 1,y,2 -> printf "2:%s" y 1,_,_ -> printf"1:" _,_,_-> printf"der Rest"
List Matching letlst= [1..10] match lst with []-> printfn"empty" [x]-> printfn"%d" x [x;y]-> printfn "%d%d" x y x::xs -> printfn"first %d" x
Match mit Guard letvalue= 10 match value with _ whenvalue< 5 ->.. _ whenvalue>= 5 ->..
Sequences Wrapper um IEnumerable<T> Mit yield können Werte erzeugt werden seq{ 1; 2; 3; }
Classes type Point = val _x : float val _y : float new (x, y) = { _x = x; _y = y } new () = { _x = 0.0; _y = 0.0 } member this.length = let sqr x = x * x sqrt < sqr this._x + sqr this._y
Interfaces type ICalculate = abstract Calc : int -> int
Weitere Themen Queries TypeProvider Memoizations Continuations Monads/ Workflows Units ofmeasure