Slide 1

Slide 1 text

May 2017 @filippovitale Using for what you don't like writing in .

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

What is Eta?

Slide 8

Slide 8 text

https://jaxenter.com/pirates-of-the-jvm-the-infographic-132524.html

Slide 9

Slide 9 text

https://jaxenter.com/pirates-of-the-jvm-the-infographic-132524.html

Slide 10

Slide 10 text

Modern Haskell on the JVM - Rahul Muttineni - github.com/typelead/eta - github.com/typelead/etlas - github.com/typelead/eta-hackage - Objectives - JVM + Haskell Ecosystems - Accessibility for beginners It is GHC 7.10.3

Slide 11

Slide 11 text

Modern Haskell on the JVM - Rahul Muttineni - github.com/typelead/eta - github.com/typelead/etlas - github.com/typelead/eta-hackage - Objectives - JVM + Haskell Ecosystems - Accessibility for beginners forked from haskell/cabal It is GHC 7.10.3

Slide 12

Slide 12 text

Modern Haskell on the JVM - Rahul Muttineni - github.com/typelead/eta - github.com/typelead/etlas - github.com/typelead/eta-hackage - Objectives - JVM + Haskell Ecosystems - Accessibility for beginners forked from haskell/cabal set of patches for particular packages from Hackage that cannot be built out-of-the-box It is GHC 7.10.3

Slide 13

Slide 13 text

What does Eta compile?

Slide 14

Slide 14 text

module Main where import System.CPUTime main :: IO () main = getCPUTime >>= print object Main extends App { println(System.nanoTime() * 1000) } https://github.com/filippovitale/eta-playground/tree/master/simplest-ghc-program

Slide 15

Slide 15 text

module Main where import System.CPUTime main :: IO () main = getCPUTime >>= print object Main extends App { println(System.nanoTime() * 1000) } λ> :t getCPUTime getCPUTime :: IO Integer

Slide 16

Slide 16 text

module Main where import System.CPUTime main :: IO () main = getCPUTime >>= print object Main extends App { println(System.nanoTime() * 1000) } λ> :t print print :: Show a => a -> IO () λ> :t getCPUTime getCPUTime :: IO Integer λ> :i Integer … instance Show Integer

Slide 17

Slide 17 text

module Main where import System.CPUTime main :: IO () main = getCPUTime >>= print object Main extends App { println(System.nanoTime() * 1000) }

Slide 18

Slide 18 text

module Main where import System.CPUTime main :: IO () main = getCPUTime >>= print object Main extends App { nanoTime() * 1000 |> println }

Slide 19

Slide 19 text

$ cat > Main.hs stack ghc Main.hs && ./Main

Slide 20

Slide 20 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ...

Slide 21

Slide 21 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... $ java -jar RunMain.jar 422227000000

Slide 22

Slide 22 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... Driver .hs ghc Core STG https://www.microsoft.com/en-us/research/wp-content/uploads/1992/04/spineless-tagless-gmachine.pdf

Slide 23

Slide 23 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... Driver Parser Typechecker Desugarer Optimizer Simplifier Code Generator .hs Core STG ghc http://www.aosabook.org/en/ghc.html

Slide 24

Slide 24 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... Driver Parser Typechecker Desugarer Optimizer Simplifier Code Generator .hs Core STG .jar

Slide 25

Slide 25 text

$ cat > Main.hs $ eta Main.hs [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... $ ls -lh -rw-r--r-- 711B Main.hi -rw-r--r-- 84B Main.hs -rw-r--r-- 3.3K Main.jar -rw-r--r-- 18M RunMain.jar - Main.jar content - all the dependencies - GHC runtime-system https://github.com/filippovitale/eta-playground/tree/master/simplest-ghc-program

Slide 26

Slide 26 text

How can we use libs from the JVM ecosystem?

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

{-# LANGUAGE MagicHash #-} module Main where import Java -- foreign import declaration foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeIO :: IO Int64 main :: IO () main = nanoTimeIO >>= print $ eta Main.hs && java -jar RunMain.jar [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... 149320110727531 IO Monad https://github.com/filippovitale/eta-playground/blob/master/java-static-import

Slide 29

Slide 29 text

{-# LANGUAGE MagicHash #-} module Main where import Java -- foreign import declaration foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeJava :: Java a Int64 main :: IO () main = java nanoTimeJava >>= print $ eta Main.hs && java -jar RunMain.jar [1 of 1] Compiling Main ( Main.hs, Main.jar ) Linking RunMain.jar ... 149319575014401 java :: Java c a -> IO a Java Monad

Slide 30

Slide 30 text

{-# LANGUAGE MagicHash #-} module Main where import Java -- foreign import declarations foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeJava :: Java a Int64 foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeIO :: IO Int64 forall a. Java a b -- isomorphic to -- IO b https://github.com/typelead/eta/issues/255#issuecomment-290937594

Slide 31

Slide 31 text

{-# LANGUAGE MagicHash #-} module Main where import Java -- foreign import declarations foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeJava :: Java a Int64 foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeIO :: IO Int64 foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimePlain :: Int64 main :: IO () main = do java nanoTimeJava >>= print java nanoTimeJava >>= print nanoTimeIO >>= print nanoTimeIO >>= print print nanoTimePlain print nanoTimePlain

Slide 32

Slide 32 text

{-# LANGUAGE MagicHash #-} module Main where import Java -- foreign import declarations foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeJava :: Java a Int64 foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimeIO :: IO Int64 foreign import java unsafe "@static java.lang.System.nanoTime" nanoTimePlain :: Int64 main :: IO () main = do java nanoTimeJava >>= print java nanoTimeJava >>= print nanoTimeIO >>= print nanoTimeIO >>= print print nanoTimePlain print nanoTimePlain $ java -jar RunMain.jar 149319575014401 149320109787317 149320110727531 149320111517553 149320112027191 149320112027191 https://github.com/filippovitale/eta-playground/blob/master/java-static-import

Slide 33

Slide 33 text

From Java static methods to full libraries

Slide 34

Slide 34 text

https://github.com/filippovitale/eta-playground/tree/master/javafx-canvas-grid

Slide 35

Slide 35 text

$ mkdir javafx-canvas-grid && cd "$_" $ etlas init && tree . ├── LICENSE ├── Setup.hs ├── javafx-canvas-grid.cabal

Slide 36

Slide 36 text

$ mkdir javafx-canvas-grid && cd "$_" $ etlas init && tree . ├── LICENSE ├── Setup.hs ├── javafx-canvas-grid.cabal └── src ├── CanvasGridApp.hs ├── JavaFX │ ├── │ ├── │ └── ├── JavaFX.hs └── Main.hs

Slide 37

Slide 37 text

$ mkdir javafx-canvas-grid && cd "$_" $ etlas init && tree . ├── LICENSE ├── Setup.hs ├── javafx-canvas-grid.cabal └── src ├── CanvasGridApp.hs ├── JavaFX │ ├── Core.hs │ ├── Methods.hs │ └── Types.hs ├── JavaFX.hs └── Main.hs

Slide 38

Slide 38 text

module JavaFX.Types where import Java data {-# CLASS "javafx.stage.Stage" #-} Stage = Stage (Object# Stage) deriving Class data {-# CLASS "javafx.scene.Scene" #-} Scene = Scene (Object# Scene) deriving Class data {-# CLASS "javafx.scene.Group" #-} Group = Group (Object# Group) deriving Class -- There is a default instance for “object arrays” data {-# CLASS "javafx.scene.canvas.Canvas" #-} Canvas = Canvas (Object# Canvas) deriving Class data {-# CLASS "javafx.scene.canvas.Canvas[]" #-} Canvases = Canvases (Object# Canvases) der... instance JArray Canvas Canvases src/JavaFX/Types.hs

Slide 39

Slide 39 text

module JavaFX.Methods where import Java import JavaFX.Types -- Stage methods foreign import java unsafe "show" show :: Java Stage () foreign import java unsafe "setTitle" setTitle :: String -> Java Stage () foreign import java unsafe "setScene" setScene :: Scene -> Java Stage () -- GraphicsContext methods foreign import java unsafe "fillOval" fillOval :: Double -> Double -> Double -> Double -> Java GraphicsContext () src/JavaFX/Methods.hs

Slide 40

Slide 40 text

import javafx.application.Application import javafx.stage.Stage class CanvasGridApp extends Application { override def start(primaryStage: Stage): Unit = { ??? } }

Slide 41

Slide 41 text

module CanvasGridApp where import Java data {-# CLASS "org.eta.CanvasGridApp extends javafx.application.Application" #-} CanvasGridApp = CanvasGridApp (Object# CanvasGridApp) start :: Stage -> Java CanvasGridApp () start primaryStage = undefined foreign export java "start" start :: Stage -> Java CanvasGridApp () src/CanvasGridApp.hs class CanvasGridApp extends Application { override def start(primaryStage: Stage): Unit = { ??? } }

Slide 42

Slide 42 text

start :: Stage -> Java CanvasGridApp () start primaryStage = do c <- newCanvas w h gc <- c <.> getGraphicsContext2D src/CanvasGridApp.hs -- Execute a Java action in the Java monad of another class -- with respect to the given object. (<.>) :: (Class c) => c -> Java c a -> Java b a

Slide 43

Slide 43 text

start :: Stage -> Java CanvasGridApp () start primaryStage = do c <- newCanvas w h gc <- c <.> getGraphicsContext2D forM_ [(i, j) | i <- [0..(n-1)], j <- [0..(n-1)]] $ \(i, j) -> gc <.> fillOval (u*i) (u*j) (u*r) (u*r) src/CanvasGridApp.hs

Slide 44

Slide 44 text

start :: Stage -> Java CanvasGridApp () start primaryStage = do c <- newCanvas w h gc <- c <.> getGraphicsContext2D forM_ [(i, j) | i <- [0..(n-1)], j <- [0..(n-1)]] $ \(i, j) -> gc <.> fillOval (u*i) (u*j) (u*r) (u*r) s <- (newGroup c) >>= newScene primaryStage <.> (setScene s >> setTitle "Eta-JavaFX CanvasGrid" >> show) where w = 320 h = 320 n = 8 u = (min w h) / n r = 0.9 src/CanvasGridApp.hs

Slide 45

Slide 45 text

$ etlas run Resolving dependencies... Configuring javafx-canvas-grid-0.1.0.0... Preprocessing executable 'javafx-canvas-grid' Building executable 'javafx-canvas-grid' [1 of 6] Compiling JavaFX.Types [2 of 6] Compiling JavaFX.Methods [3 of 6] Compiling JavaFX.Core [4 of 6] Compiling JavaFX [5 of 6] Compiling CanvasGridApp [6 of 6] Compiling Main Linking dist/build/javafx-canvas-grid/javafx-canvas-grid.jar ... Running javafx-canvas-grid... https://github.com/filippovitale/eta-playground/tree/master/javafx-canvas-grid

Slide 46

Slide 46 text

Old school Demoscene

Slide 47

Slide 47 text

https://pouet.net/

Slide 48

Slide 48 text

http://www.p01.org/

Slide 49

Slide 49 text

http://jamie-wong.com/2016/07/15/ray-marching-signed-distance-functions/ http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf Signed Distance Function http://www.p01.org/tea_storm/ Here be Dragons

Slide 50

Slide 50 text

start :: Stage -> Java TeaStormApp () start primaryStage = do t0 <- nanoTime c <- newCanvas w h s <- (newGroup c) >>= newScene loop <- newAnimationLoop c t0 n u m loop <.> startAnimation primaryStage <.> (setTitle "Eta-JavaFX TeaStorm" >> setScene s >> show) where n = 96 m = 10 w = n * m h = n * m u = (min w h) / n src/TeaStormApp.hs https://github.com/filippovitale/eta-playground/tree/master/javafx-teastorm

Slide 51

Slide 51 text

start :: Stage -> Java TeaStormApp () start primaryStage = do t0 <- nanoTime c <- newCanvas w h s <- (newGroup c) >>= newScene loop <- newAnimationLoop c t0 n u m loop <.> startAnimation primaryStage <.> (setTitle "Eta-JavaFX TeaStorm" >> setScene s >> show) where n = 96 m = 10 w = n * m h = n * m u = (min w h) / n src/TeaStormApp.hs

Slide 52

Slide 52 text

name: javafx-teastorm version: 0.1.0.0 homepage: https://github.com/filippovitale/eta-playground/javafx-teastorm executable javafx-teastorm main-is: Main.hs java-sources: java/teastorm/AnimationLoop.java build-depends: base >=4.8 && <4.9 hs-source-dirs: src default-language: Haskell2010 javafx-teastorm.cabal

Slide 53

Slide 53 text

public class AnimationLoop extends AnimationTimer { public AnimationLoop(Canvas c, long t0, double n, double u, double m) {...} private static double computeIntensity(final double x, final double y, final double s, final double t) { double intensity = 1; for (double d = intensity * 4, df = 1; .025 < df * intensity; intensity -= .025) { double X = d * x / s - d / 2; double Y = d * y / s - d / 2; double Z = d / 2 - 9; df = (X * X + Y * Y * Math.cos(t/6 + Math.cos(d - X - Y)) + Z * Z) / 12 - 1 + Math.cos(X + t) * Math.cos(Y - t); d += df; } return intensity; } @Override public void handle(long currentNanoTime) { double t = (currentNanoTime - t0) / (500 * oneMillisecondInNanoTime); gc.clearRect(0, 0, w, h); // clear the Canvas for (int x = 0; x < n; x++) { for (int y = 0; y < n; y++) { double i = computeIntensity(x, y, n, t); gc.setGlobalAlpha(i); gc.fillOval(x * u, y * u, i * m * 1.4, i * m * 1.4); } } } }

Slide 54

Slide 54 text

$ etlas run Resolving dependencies... Configuring javafx-teastorm-0.1.0.0... Preprocessing executable 'javafx-teastorm' for javafx-teastorm-0.1.0.0.. Building executable 'javafx-teastorm' for javafx-teastorm-0.1.0.0.. [1 of 6] Compiling JavaFX.Types [2 of 6] Compiling JavaFX.Methods [3 of 6] Compiling TeaStormApp [4 of 6] Compiling JavaFX.Core [5 of 6] Compiling JavaFX [6 of 6] Compiling Main Linking dist/build/javafx-teastorm/javafx-teastorm.jar ... Running javafx-teastorm... https://github.com/filippovitale/eta-playground/tree/master/javafx-teastorm

Slide 55

Slide 55 text

Eta is embeddable: you can export Haskell functions to the JVM

Slide 56

Slide 56 text

Source Sink

Slide 57

Slide 57 text

Boba Fett WARAWHWHAHOR

Slide 58

Slide 58 text

FileIO.fromPath(jsonPath) .via(gunzip()) .via(lineSplitter) .map(_.utf8String) .via(extractNameFlow) .via(wookieeFlow) .runWith(Sink.foreach(println)) extractNameFlow wookieeFlow https://github.com/filippovitale/eta-playground/tree/master/scala-akka-stream-eta-wookiee

Slide 59

Slide 59 text

name: scala-akka-stream-eta-wookiee version: 0.1.0.0 cabal-version: >=1.10 executable scala-akka-stream-eta-wookiee main-is: Main.hs build-depends: base >=4.8 && <4.9, bytestring, containers, aeson hs-source-dirs: src default-language: Haskell2010 -- java-sources: lib/manually-downloaded-akka-stream-uber.jar

Slide 60

Slide 60 text

name: scala-akka-stream-eta-wookiee version: 0.1.0.0 cabal-version: >=1.10 executable scala-akka-stream-eta-wookiee main-is: Main.hs build-depends: base >=4.8 && <4.9, bytestring, containers, aeson hs-source-dirs: src default-language: Haskell2010 maven-depends: com.typesafe.akka:akka-stream_2.12:2.4.17

Slide 61

Slide 61 text

name: scala-akka-stream-eta-wookiee version: 0.1.0.0 cabal-version: >=1.10 executable scala-akka-stream-eta-wookiee main-is: Main.hs build-depends: base >=4.8 && <4.9, bytestring, containers, aeson hs-source-dirs: src default-language: Haskell2010 maven-depends: com.typesafe.akka:akka-stream_2.12:2.4.17

Slide 62

Slide 62 text

src/AkkaStream/Exports.hs data {-# CLASS "stream.Example" #-} Example = Example (Object# Example) type JStringFlow = Flow JString JString NotUsed extractNameFlow :: Java Example JStringFlow extractNameFlow = undefined wookieeFlow :: Java Example JStringFlow wookieeFlow = undefined foreign export java extractNameFlow :: Java Example JStringFlow foreign export java wookieeFlow :: Java Example JStringFlow

Slide 63

Slide 63 text

src/AkkaStream/Exports.hs data {-# CLASS "stream.Example" #-} Example = Example (Object# Example) type JStringFlow = Flow JString JString NotUsed extractNameFlow :: Java Example JStringFlow extractNameFlow = flowFromFunction $ applyFunction f where f js = undefined wookieeFlow :: Java Example JStringFlow wookieeFlow = flowFromFunction $ applyFunction f where f js = undefined foreign export java extractNameFlow :: Java Example JStringFlow foreign export java wookieeFlow :: Java Example JStringFlow akka.stream.javadsl.Flow.fromFunction static Flow fromFunction(Function f)

Slide 64

Slide 64 text

src/AkkaStream/Exports.hs data {-# CLASS "stream.Example" #-} Example = Example (Object# Example) type JStringFlow = Flow JString JString NotUsed extractNameFlow :: Java Example JStringFlow extractNameFlow = flowFromFunction $ applyFunction f where f js = undefined wookieeFlow :: Java Example JStringFlow wookieeFlow = flowFromFunction $ applyFunction f where f js = undefined foreign export java extractNameFlow :: Java Example JStringFlow foreign export java wookieeFlow :: Java Example JStringFlow akka.japi.function.Function trait Function[-T, +R] { def apply(param: T): R }

Slide 65

Slide 65 text

src/AkkaStream/Exports.hs data {-# CLASS "stream.Example" #-} Example = Example (Object# Example) type JStringFlow = Flow JString JString NotUsed extractNameFlow :: Java Example JStringFlow extractNameFlow = flowFromFunction $ applyFunction f where f js = return (toJava $ g $ pack (fromJava js :: [Char])) g s = (fromMaybe empty (decode s :: Maybe (Map String String))) ! "name" wookieeFlow :: Java Example JStringFlow wookieeFlow = flowFromFunction $ applyFunction f where f js = return (toJava $ (fromJava js :: [Char]) >>= wookiee) foreign export java extractNameFlow :: Java Example JStringFlow foreign export java wookieeFlow :: Java Example JStringFlow

Slide 66

Slide 66 text

src/main/scala/stream/Main.scala object Main extends App { val e = new Example() val extractNameFlow = e.extractNameFlow() val wookieeFlow = e.wookieeFlow() val jsonURL = getClass.getResource("/all_characters.json-stream.gz") val jsonPath = Paths.get(jsonURL.toURI) val lineSplitter = Framing.delimiter(ByteString("\n"), Int.MaxValue) FileIO.fromPath(jsonPath) .via(gunzip()) .via(lineSplitter) .map(_.utf8String) .via(extractNameFlow) .via(wookieeFlow) .runWith(Sink.foreach(println)) .onComplete(_ => system.terminate()) }

Slide 67

Slide 67 text

https://github.com/filippovitale/eta-playground/tree/master/scala-akka-stream-eta-wookiee

Slide 68

Slide 68 text

Where Eta is going?

Slide 69

Slide 69 text

- Interactive REPL - Java FFI imports aid / helpers - Hot-code reloading as JVM has “built-in dynamism” - GraalVM on JDK9 - New JIT Compiler and - Polyglot Runtime for the JVM - Stability - Support for the fundamental Hackage libraries Eta active development areas

Slide 70

Slide 70 text

May 2017 @filippovitale Thanks!

Slide 71

Slide 71 text

May 2017 @filippovitale $ tail -f questions