Fay Haskell auf Client-Seite von Alexander Mills Inhalt ● Was ist Fay? Inhalt ● Was ist Fay? ○ Motivation Inhalt ● Was ist Fay? ○ Motivation ● Wie arbeitet Fay? Inhalt ● Was ist Fay? ○ Motivation ● Wie arbeitet Fay? ○ FFI Inhalt ● Was ist Fay? ○ Motivation ● Wie arbeitet Fay? ○ FFI ○ Codebeispiele Inhalt ● Was ist Fay? ○ Motivation ● Wie arbeitet Fay? ○ FFI ○ Codebeispiele ● Was kann Fay nicht? Inhalt ● Was ist Fay? ○ Motivation ● Wie arbeitet Fay? ○ FFI ○ Codebeispiele ● Was kann Fay nicht? ● Fazit Das JavaScript-Problem Das JavaScript-Problem "JavaScript sucks!" Das JavaScript-Problem "JavaScript sucks!" versus "We need JavaScript!" Das JavaScript-Problem Nachteile: Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung ● späte Bindung Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung ● späte Bindung ● automatische Typkonversion Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung ● späte Bindung ● automatische Typkonversion ● keine statischen Typen Vorteile: Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung ● späte Bindung ● automatische Typkonversion ● keine statischen Typen Vorteile: ● Plattform für Webdevelopment Das JavaScript-Problem Nachteile: ● schwach typisiert ● keine Modularisierung ● späte Bindung ● automatische Typkonversion ● keine statischen Typen Vorteile: ● Plattform für Webdevelopment ● Unterstützung für alle aktuellen Betriebssysteme und Browser Die Lösung Die Lösung Compiler Die Lösung Compiler Existierende Sprache, die nicht die Probleme von JavaScript hat, nach JavaScript übersetzen. Die Lösung Compiler Existierende Sprache, die nicht die Probleme von JavaScript hat, nach JavaScript übersetzen. Sprache der Wahl: Die Lösung Compiler Existierende Sprache, die nicht die Probleme von JavaScript hat, nach JavaScript übersetzen. Sprache der Wahl: Haskell Die Lösung Compiler Existierende Sprache, die nicht die Probleme von JavaScript hat, nach JavaScript übersetzen. Sprache der Wahl: Haskell Quelle: haskell.org Was ist Fay? Was ist Fay? ● Haskell zu JavaScript Compiler Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell ● Setzt Eigenschaften von Haskell um Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell ● Setzt Eigenschaften von Haskell um ○ Statische Typisierung Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell ● Setzt Eigenschaften von Haskell um ○ Statische Typisierung ○ Lazy Evaluation Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell ● Setzt Eigenschaften von Haskell um ○ Statische Typisierung ○ Lazy Evaluation ● Bietet Support für Grunddatentypen (Double, String, Integer, Boolean, etc.) Was ist Fay? ● Haskell zu JavaScript Compiler ● Unterstützt eine Untermenge von Haskell ● Setzt Eigenschaften von Haskell um ○ Statische Typisierung ○ Lazy Evaluation ● Bietet Support für Grunddatentypen (Double, String, Integer, Boolean, etc.) ● Möglichkeit JavaScript-Funktionalität (z.B. Zugriff auf DOM Struktur) zu benutzen mittels FFI Arbeitsweise Wie kompiliert Fay? Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Fay-Laufzeit Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Fay-Laufzeit ○ Listen, Monaden, arithmetische Operationen Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Fay-Laufzeit ○ Listen, Monaden, arithmetische Operationen ○ Thunks für Lazy Evaluation Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Fay-Laufzeit ○ Listen, Monaden, arithmetische Operationen ○ Thunks für Lazy Evaluation ● Haskell Prelude Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Fay-Laufzeit ○ Listen, Monaden, arithmetische Operationen ○ Thunks für Lazy Evaluation ● Haskell Prelude ● Das eigentliche Programm Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Klassenkonstruktor mit Inhalt: ○ Fay-Laufzeit ■ Listen, Monaden, arithmetische Operationen ■ Thunks für Lazy Evaluation ○ Haskell Prelude ○ Das eigentliche Programm Arbeitsweise: Grundschema Aufbau des zu erzeugenden JavaScript-Codes: ● Klassenkonstruktor mit Inhalt: ○ Fay-Laufzeit ■ Listen, Monaden, arithmetische Operationen ■ Thunks für Lazy Evaluation ○ Haskell Prelude ○ Das eigentliche Programm ● Erzeugen einer Instanz der Klasse und Aufruf der Hauptfunktion Arbeitsweise: Grundschema Namenskonvention: Modulname$Funktionsname Arbeitsweise: Grundschema Namenskonvention: Modulname$Funktionsname Ist im Haskellcode kein Modulname festgelegt => Main Arbeitsweise: Grundschema Namenskonvention: Modulname$Funktionsname Ist im Haskellcode kein Modulname festgelegt => Main Beispiele: Fay$$add, Prelude$id, Main$main Arbeitsweise: Grundschema var Main = function() { /* Fay Runtime */ /* Prelude */ /* Mein Programm */ }; var main = new Main(); main.Main$main(); Arbeitsweise: Grundschema var Main = function() { /* Fay Runtime */ /* Prelude */ /* Mein Programm */ }; var main = new Main(); main._(main.Main$main); Arbeitsweise: Thunks Arbeitsweise: Thunks Thunks sind (noch) nicht berechnete Werte. Arbeitsweise: Thunks Thunks sind (noch) nicht berechnete Werte. Alle übersetzten Funktionen werden bei der Kompilierung in Thunks gelagert. Arbeitsweise: Thunks Thunks sind (noch) nicht berechnete Werte. Alle übersetzten Funktionen werden bei der Kompilierung in Thunks gelagert. Zur Laufzeit enthält ein Thunk entweder einen Funktionszeiger oder einen Wert. Arbeitsweise: Thunks ... function Fay$$$(value){ this.forced = false; this.value = value; } ... var Main$main = new Fay$$$(function(){...}); ... Arbeitsweise: Thunks ... function Fay$$$(value){ this.forced = false; this.value = value; } ... var Main$main = new Fay$$$(function(){...}); ... Arbeitsweise: Thunks ... function Fay$$$(value){ this.forced = false; this.value = value; } ... var Main$main = new Fay$$$(function(){...}); ... Arbeitsweise: Thunks Im Thunk gelagerter Wert wird über eine "force" Funktion evaluiert. Arbeitsweise: Thunks Im Thunk gelagerter Wert wird über eine "force" Funktion evaluiert. Thunk schon berechnet => return value Arbeitsweise: Thunks Im Thunk gelagerter Wert wird über eine "force" Funktion evaluiert. Thunk schon berechnet => return value Thunk noch nicht berechnet => return value() Arbeitsweise: Thunks Im Thunk gelagerter Wert wird über eine "force" Funktion evaluiert. Thunk schon berechnet => return value Thunk noch nicht berechnet => return value() Parameter ist kein Thunk => return Parameter Arbeitsweise: Thunks Im Thunk gelagerter Wert wird über eine "force" Funktion evaluiert. Thunk schon berechnet => return value Thunk noch nicht berechnet => return value() Parameter ist kein Thunk => return Parameter "force" => "_", bzw "Fay$$_" Arbeitsweise: Funktionen Arbeitsweise: Funktionen Funktionen werden als Parameter für den Konstruktor eines Thunks übergeben. Arbeitsweise: Funktionen Funktionen werden als Parameter für den Konstruktor eines Thunks übergeben. Für jeden Parameter dieser Funktion wird ein Wrapper um den Konstruktor gelegt. Arbeitsweise: Funktionen f :: a => var Main$f = new Fay$$$(function(){...}) Arbeitsweise: Funktionen f :: a -> a => var Main$f = function($p1){ return new Fay$$$(function(){...}) }; Arbeitsweise: Funktionen f :: a -> a -> a => var Main$f = function($p1){ return function($p2){ return new Fay$$$(function(){...}) }; }; Arbeitsweise: Funktionen Für jeden einzelnen Parameter ein Aufruf von "force": Arbeitsweise: Funktionen Für jeden einzelnen Parameter ein Aufruf von "force": f :: a -> a Fay$$_(Main$f)(p1) Arbeitsweise: Funktionen Für jeden einzelnen Parameter ein Aufruf von "force": f :: a -> a Fay$$_(Main$f)(p1) f :: a -> a -> a Fay$$_(Fay$$_(Main$f)(p1))(p2) Arbeitsweise: Funktionen "force" liefert jeweils den Funktionszeiger zurück (keinen Thunk). Arbeitsweise: Funktionen "force" liefert jeweils den Funktionszeiger zurück (keinen Thunk). Das letzte "force" liefert einen Thunk zurück, in welchem die eigentliche Funktion gelagert ist. Arbeitsweise: Funktionen "force" liefert jeweils den Funktionszeiger zurück (keinen Thunk). Das letzte "force" liefert einen Thunk zurück, in welchem die eigentliche Funktion gelagert ist. Anwendung "force" auf den Thunk startet die Auswertung dieser Funktion. Arbeitsweise: Ein Beispiel Arbeitsweise: Ein Beispiel Simples Haskell-Programm: Arbeitsweise: Ein Beispiel Simples Haskell-Programm: module Demo(main) where f :: Int -> Int f0=0 f1=1 f n = f (n-1) + f (n-2) main = putStrLn (show (f 10)) Arbeitsweise: Ein Beispiel f :: Int -> Int f0=0 f1=1 f n = f (n-1) + f (n-2) => Arbeitsweise: Ein Beispiel f :: Int -> Int f0=0 f1=1 f n = f (n-1) + f (n-2) => var Demo$f = function($p1) { return new Fay$$$(function() { ... }; }; Arbeitsweise: Ein Beispiel f :: Int -> Int f0=0 f1=1 f n = f (n-1) + f (n-2) => var Demo$f = function($p1) { return new Fay$$$(function() { ... }; }; Arbeitsweise: Patternmatching f0=0 => if (Fay$$_($p1) === 0) { return 0; } Arbeitsweise: Patternmatching f1=1 => if (Fay$$_($p1) === 1) { return 1; } Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return Fay$$_(Fay$$_(Fay$$add)(Fay$$_(Demo$f) (Fay$$_(Fay$$_(Fay$$sub)(n))(1))))(Fay$$_ (Demo$f)(Fay$$_(Fay$$_(Fay$$sub)(n))(2))); Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return Fay$$_(Fay$$_(Fay$$add) (Fay$$_(Demo$f) (Fay$$_(Fay$$_(Fay$$sub)(n))(1)))) (Fay$$_(Demo$f) (Fay$$_(Fay$$_(Fay$$sub)(n))(2))); Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return Fay$$_(Fay$$_(Fay$$add) (Fay$$_(Demo$f) (Fay$$_(Fay$$_(Fay$$sub)(n))(1)))) (Fay$$_(Demo$f) (Fay$$_(Fay$$_(Fay$$sub)(n))(2))); Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return Fay$$_(Fay$$_(Fay$$add) (Fay$$_(Demo$f)(n-1))) (Fay$$_(Demo$f)(n-2))); Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return Fay$$_(Fay$$_(Fay$$add) (f (n-1))) (f (n-2))); Arbeitsweise: Ein Beispiel f n = f (n-1) + f (n-2) => return (f (n-1)) + (f (n-2)); Arbeitsweise: Datentypen Arbeitsweise: Datentypen ● JavaScript hat dynamische Typisierung Arbeitsweise: Datentypen ● JavaScript hat dynamische Typisierung ● Keine Typüberprüfung zur Laufzeit Arbeitsweise: Datentypen ● JavaScript hat dynamische Typisierung ● Keine Typüberprüfung zur Laufzeit ● Korrekte Typverwendung bei Funktionen beim Kompilieren mit Fay geprüft Arbeitsweise: Datentypen ● JavaScript hat dynamische Typisierung ● Keine Typüberprüfung zur Laufzeit ● Korrekte Typverwendung bei Funktionen beim Kompilieren mit Fay geprüft f :: Int -> String main = putStrln (f "hallo Welt") => Compilerfehler Summendatentypen Patternmatching mit Konstruktoren Summendatentypen Patternmatching mit Konstruktoren data Wert = Zahl Int | Text String f :: Wert -> String f (Zahl i) = "Eine Zahl: " ++ (show i) f (Text s) = "Ein Text: " ++ s Summendatentypen Fay übersetzt die Konstruktoren des Summendatentyps: Summendatentypen Fay übersetzt die Konstruktoren des Summendatentyps: var $_Main$Zahl = function(slot1){ this.slot1 = slot1; }; var $_Main$Text = function(slot1){ this.slot1 = slot1; }; Summendatentypen Patternmatching mit "instanceof" ... if (Fay$$_($p1) instanceof $_Main$Zahl) {...} ... Arbeitsweise: Listen Arbeitsweise: Listen //Konstruktor für Liste function Fay$$Cons(car,cdr){ this.car = car; // Erstes Element this.cdr = cdr;// Restliste } Arbeitsweise: Listen //Konstruktor für Liste function Fay$$Cons(car,cdr){ this.car = car; // Erstes Element this.cdr = cdr;// Restliste } car: Contents of Adress part of Register number cdr: Contents of Decrement part of Register number Arbeitsweise: Listen //Konstruktor für Liste function Fay$$Cons(car,cdr){ this.car = car; // Erstes Element this.cdr = cdr;// Restliste } function Fay$$cons(x){ return function(y){ return new Fay$$Cons(x,y); }; } Arbeitsweise: Listen [1,2,3] => [1..10] => [1..] => "Fay ist toll" => Arbeitsweise: Listen [1,2,3] => Fay$$list([1,2,3]) [1..10] => Prelude$enumFromTo(1)(10) [1..] => Prelude$enumFrom(1) "Fay ist toll" => Fay$$list("Fay ist toll") Arbeitsweise: Listen ● Fay$$list Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom ○ Parameter wird erstes Element der Liste Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom ○ Parameter wird erstes Element der Liste ○ Restliste ein Thunk Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom ○ Parameter wird erstes Element der Liste ○ Restliste ein Thunk ■ Cons(i, Prelude$enumFrom(i+1)) Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom ○ Parameter wird erstes Element der Liste ○ Restliste ein Thunk ■ Cons(i, Prelude$enumFrom(i+1)) ● Prelude$enumFromTo Arbeitsweise: Listen ● Fay$$list ○ Arbeitet Eingabearray von hinten nach vorne ab ○ Rückgabe z.B.: Cons(1,Cons(2,Cons(3, null))) ● Prelude$enumFrom ○ Parameter wird erstes Element der Liste ○ Restliste ein Thunk ■ Cons(i, Prelude$enumFrom(i+1)) ● Prelude$enumFromTo ○ Wie Prelude$enumFrom, aber mit Abbruchbedingung Arbeitsweise: Listen Beispiel für Lazy Evaluation Arbeitsweise: Listen Beispiel für Lazy Evaluation head [1..] Arbeitsweise: Listen Beispiel für Lazy Evaluation head [1..] => head Fay$$Cons(1, Thunk) Arbeitsweise: Listen Beispiel für Lazy Evaluation head [1..] => head Fay$$Cons(1, Thunk) => 1 Foreign Function Interface Foreign Function Interface Kein Zugriff auf Elemente einer HTML Seite. Foreign Function Interface Kein Zugriff auf Elemente einer HTML Seite. Fay bietet "FFI" um dem entgegenzukommen. Foreign Function Interface Kein Zugriff auf Elemente einer HTML Seite. Fay bietet "FFI" um dem entgegenzukommen. Stellt die Möglichkeit dar, um direkt JavaScriptcode in Haskell zu verwenden. Foreign Function Interface module Hello(main) where import FFI alert :: String -> Fay() alert = ffi "alert(%1)" main = alert "Hello World" Foreign Function Interface "ffi" hat genau einen Parameter (String)! Foreign Function Interface "ffi" hat genau einen Parameter (String)! Punktfreie Notation notwendig! Foreign Function Interface Punktfreie Notation: plusOne :: Int -> Int plusOne x = 1 + x Foreign Function Interface Punktfreie Notation: plusOne :: Int -> Int plusOne x = 1 + x //gleichwertig mit plusOne x = (+) 1 x Foreign Function Interface Punktfreie Notation: plusOne :: Int -> Int plusOne x = 1 + x //gleichwertig mit plusOne x = (+) 1 x //gleichwertig mit plusOne = (+) 1 Foreign Function Interface Punktfreie Notation: plusOne x = (+) 1 x => nicht Punktfrei plusOne = (+) 1 => Punktfrei Foreign Function Interface "ffi" hat genau einen Parameter (String)! Punktfreie Notation notwendig! "%1", "%2", "%3", etc. innerhalb des Strings werden ersetzt durch die Parameter der Funktion. Foreign Function Interface Der Parameter von "ffi" wird als JavaScriptcode interpretiert. Foreign Function Interface Der Parameter von "ffi" wird als JavaScriptcode interpretiert. Keinerlei Compilerprüfung dieses Codes. Foreign Function Interface Der Parameter von "ffi" wird als JavaScriptcode interpretiert. Keinerlei Compilerprüfung dieses Codes. => Fehleranfällig Foreign Function Interface "ffi" ist nur eine Pseudofunktion. Foreign Function Interface "ffi" ist nur eine Pseudofunktion. Fay setzt den Stringparameter als JavaScriptcode in die kompilierte Funktion ein. Foreign Function Interface "ffi" ist nur eine Pseudofunktion. Fay setzt den Stringparameter als JavaScriptcode in die kompilierte Funktion ein. => Der Haskellcode lässt sich mit "ffi" nicht mehr im GHC kompilieren!!! Foreign Function Interface ffi :: String -> a ffi = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context." Foreign Function Interface ffi :: String -> a ffi = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context." Foreign Function Interface ffi :: String -> a ffi = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context." Typsignatur der aufrufenden Funktion bestimmt Konversionsverhalten im generierten Code. Foreign Function Interface round :: Double -> Int round = ffi "Math.round(%1)" Foreign Function Interface round :: Double -> Int round = ffi "Math.round(%1)" => return Fay$$jsToFay_int (Math.round(Fay$$fayToJs_double($p1))); Foreign Function Interface round :: Double -> Int round = ffi "Math.round(%1)" => return Fay$$jsToFay_int (Math.round(Fay$$fayToJs_double($p1))); Foreign Function Interface alert :: String -> Fay() alert = ffi "alert(%1)" Foreign Function Interface alert :: String -> Fay() alert = ffi "alert(%1)" => var Fib$alert = function($p1){ return new Fay$$$(function(){ return new Fay$$Monad (Fay$$jsToFay(["unknown"], alert(Fay$$FayToJs_string($p1)))); }); }; Foreign Function Interface alert :: String -> Fay() alert = ffi "alert(%1)" => var Fib$alert = function($p1){ return new Fay$$$(function(){ return new Fay$$Monad (Fay$$jsToFay(["unknown"], alert(Fay$$FayToJs_string($p1)))); }); }; Foreign Function Interface Wird die Fay-Monade erstellt, wird "alert" ausgeführt. Foreign Function Interface Wird die Fay-Monade erstellt, wird "alert" ausgeführt. Der Rückgabewert von "alert" wird in der FayMonade gespeichert. Foreign Function Interface Wird die Fay-Monade erstellt, wird "alert" ausgeführt. Der Rückgabewert von "alert" wird in der FayMonade gespeichert. Fay-Monade zum "Ignorieren" des Rückgabewertes eines ffi-Aufrufs. FFI Beispiele FFI Beispiele Online Fibonacci-Rechner Live FFI Beispiele Eingabedatenprüfer Live Einschränkungen Was kann Fay nicht? Einschränkungen ● Kein Support für Typklassen Einschränkungen ● Kein Support für Typklassen ○ Funktionen wie "read" nicht implementiert Einschränkungen ● Kein Support für Typklassen ○ Funktionen wie "read" nicht implementiert ○ ffi "parseInt(%1)" kann dies jedoch ersetzen Einschränkungen ● Kein Support für Typklassen ○ Funktionen wie "read" nicht implementiert ○ ffi "parseInt(%1)" kann dies jedoch ersetzen ● "Import" unterstützt nicht übliche Haskellbibliotheken Einschränkungen ● Kein Support für Typklassen ○ Funktionen wie "read" nicht implementiert ○ ffi "parseInt(%1)" kann dies jedoch ersetzen ● "Import" unterstützt nicht übliche Haskellbibliotheken ○ Prelude und FFI Einschränkungen ● Kein Support für Typklassen ○ Funktionen wie "read" nicht implementiert ○ ffi "parseInt(%1)" kann dies jedoch ersetzen ● "Import" unterstützt nicht übliche Haskellbibliotheken ○ Prelude und FFI ○ z.B. kein Control.Monad, Data.Map, etc Einschränkungen ● Numbercrunching nur bedingt möglich Einschränkungen ● Numbercrunching nur bedingt möglich ○ JavaScript speichert alle Zahlen als Doubles Einschränkungen ● Numbercrunching nur bedingt möglich ○ JavaScript speichert alle Zahlen als Doubles ○ Größere Zahlen als bei Int in Haskell möglich Einschränkungen ● Numbercrunching nur bedingt möglich ○ JavaScript speichert alle Zahlen als Doubles ○ Größere Zahlen als bei Int in Haskell möglich ○ Nur etwa die ersten 15 Stellen genau Einschränkungen ● Numbercrunching nur bedingt möglich ○ JavaScript speichert alle Zahlen als Doubles ○ Größere Zahlen als bei Int in Haskell möglich ○ Nur etwa die ersten 15 Stellen genau ● Sobald "FFI" importiert ist, kann der Haskellcode nicht mehr im GHC kompiliert werden Einschränkungen ● Numbercrunching nur bedingt möglich ○ JavaScript speichert alle Zahlen als Doubles ○ Größere Zahlen als bei Int in Haskell möglich ○ Nur etwa die ersten 15 Stellen genau ● Sobald "FFI" importiert ist, kann der Haskellcode nicht mehr im GHC kompiliert werden ○ Schränkt die Testmöglichkeiten stark ein Fazit Ist Fay großartig? Fazit Ist Fay großartig? Antwort: Jein! Fazit ● Einfache Webapplikationen sind kompiliert viel größer als gleichwertiges JS-Programm Fazit ● Einfache Webapplikationen sind kompiliert viel größer als gleichwertiges JS-Programm ● Mathematische Funktionen leicht in Haskell programmierbar Fazit ● Einfache Webapplikationen sind kompiliert viel größer als gleichwertiges JS-Programm ● Mathematische Funktionen leicht in Haskell programmierbar ● FFI ermöglicht nicht-funktionale Programmierung Fazit ● Einfache Webapplikationen sind kompiliert viel größer als gleichwertiges JS-Programm ● Mathematische Funktionen leicht in Haskell programmierbar ● FFI ermöglicht nicht-funktionale Programmierung ● (Bisher) Fehlen von Haskellmodulen wie Control, Data, etc. Fazit Fay ist ein interessanter Ansatz... Fazit Fay ist ein interessanter Ansatz... ...aber noch nicht produktiv einsetzbar. Fazit Fay ist ein interessanter Ansatz... ...aber noch nicht produktiv einsetzbar. Die Betonung liegt auf "noch". Fragen? Ende