GUIs in Haskell

Cross-platform GUIs

FFI

GTK

Side effects?

IO

f1 = putStrLn "Hello World"
f2 = print 42
Prelude> :t putStrLn
putStrLn :: String -> IO ()
Prelude> :t print
print :: (Show a) => a -> IO ()
Prelude> :t readLn
readLn :: (Read a) => IO a

In short, Haskell is the world’s finest imperative programming language - Simon Peyton Jones, Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell

Sequencing actions :: do notation

main = do
    n <- readLn
    print $ n + 1
main = do
    n <- readLn
    let ans = 42
    print $ n + ans

Actions changing the world

main = do
    n <- readLn
    print $ n + 1

Monads

class Monad m where
    (>>=) :: m a -> (a -> m b) -> m b
    (>>) :: m a -> m b -> m b
    return :: a -> m a
main = do
    return 4
    print 5

List is a monad too!

instance  Monad []  where
    m >>= k  = foldr ((++) . k) [] m
    m >> k   = foldr ((++) . (\ _ -> k)) [] m
    return x = [x]
g l1 l2 = [(x, y) | x <- l1, y <-l2]
f l1 l2 = do
    x <- l1
    y <- l2
    return (x, y)

More monads

f l1 l2 = do
    x <- l1
    y <- l2
    return $ x + y
f readLine readLine
f (Just 3) (Just 4)
f (Just 3) Nothing

First window

import Graphics.Rendering.Cairo
import Graphics.UI.Gtk

main = do
  initGUI
  window <- windowNew
  widgetShowAll window
  mainGUI

Closing the window

import Graphics.Rendering.Cairo
import Graphics.UI.Gtk

main = do
  initGUI
  window <- windowNew
  window `on` deleteEvent $ liftIO mainQuit >> return False
  widgetShowAll window
  mainGUI

Window details

import Graphics.Rendering.Cairo
import Graphics.UI.Gtk

main = do
  initGUI
  window <- windowNew
  window `on` deleteEvent $ liftIO mainQuit >> return False
  windowSetGeometryHints window (Nothing :: Maybe Window)
    (Just (800, 600)) (Just (800, 600)) Nothing Nothing Nothing
  set window [ windowTitle := "First GUI app" ]
  widgetShowAll window
  mainGUI

FRP

counter :: Behavior Int
counter = accumulate ($) 0
            (fmap (+1) eventUp
             `union` fmap (subtract 1) eventDown)

End