WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt...

46
wxHaskell Daan Leijen

Transcript of WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt...

Page 1: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

wxHaskell

Daan Leijen

Page 2: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Ok….

Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren?

Doaitse

On donderdag, september 18, 2003, at 10:43 AM, Daan Leijen wrote:

Nog even over AFP. De turtle-graphics opdracht is volgensmij goed te doen met wxHaskell -- behalve dan dat hetgeinstalleerd dient te worden. Als je wilt kunnen we misschien wat details afspreken endat ik dan wat help om de opdracht vorm te geven met1) een werkend voorbeeld, en 2) concrete vragen.

Page 3: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Overview

wxHaskell as a concrete example of FFI, phantom types, existential types, combinator design, inheritance simulation, and IO as first-class values.

Homework: implement a "turtle" graphics combinator library.

Page 4: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

wxHaskell

wxHaskell is a portable GUI library for Haskell build upon the wxWindows (C++) library.

Two layers: a "core" binding (WXCore) and a haskellized layer (WX).

Page 5: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Hello world

hello :: IO ()hello = do f    <- frame    [text := "Hello!"] quit <- button f [text := "Quit" ,on command := close f] set f [layout := widget quit]

Page 6: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Layout combinators

set f [layout := margin 10 (column 5 [floatCentre (label "Hello") ,floatCentre (widget quit) ] ) ]

Page 7: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Demo

Page 8: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

What is needed?

Foreign Function Interface (FFI) Model inheritance Create abstractions:

– Layout combinators– Properties (get/set)

Page 9: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

FFI

What are the primitives that you need to interface to the imperative world from Haskell?

Page 10: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

4 primitive operations are needed.

1. Call the outside world (foreign import)

2. Be called (foreign export)

3. Use foreign data (CInt, Addr)

4. Export haskell data (StablePtr a)

Page 11: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Examples:

foreign import sin :: Double -> IO Double

foreign import strlen :: Addr -> IO CInt

Page 12: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Phantom types

Make "Addr" typesafe:

type Ptr a = Addr

foreign import strlen :: Ptr Char -> IO Int

Page 13: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Abstraction

foreign import strlen :: Ptr Char -> IO Int

strLen :: String -> IntstrLen s = unsafePerformIO $ withCString s $ \cstr -> strlen cstr

Page 14: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Abstraction

withCString :: String -> (Ptr Char -> IO a) -> IO awithCString s f = do p <- malloc (length s+1) mapM_ (poke p) (zip s [0..]) x <- f p free p return x

Page 15: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

wxHaskell

windowSetLabel :: Window a -> String -> IO ()windowSetLabel w txt = withCString txt $ \cstr -> primWindowSetLabel w txt

foreign import "windowSetLabel" primWindowSetLabel :: Window a -> Ptr Char -> IO ()

Page 16: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Inheritance

How to model inheritance?

class Window { void setLabel( const char* txt ); ..};

class Frame : public Window { void maximize( void ); ..};

Page 17: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Simple model.

type Window = Ptr CWindowdata CWindow = CWindow

type Frame = Ptr CFramedata CFrame = CFrame

windowCreate :: IO WindowwindowSetLabel :: Window -> String -> IO ()

frameCreate :: IO FrameframeMaximize :: Frame -> IO ()

Page 18: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Conversions?

windowFromFrame :: Frame -> Window

do f <- frameCreate windowSetLabel (windowFromFrame f)

Page 19: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Encode inheritance in phantom type

type Window a = Ptr (CWindow a)data CWindow a = CWindow

type Frame a = Window (CFrame a)data CFrame a = CFrame

windowCreate :: IO (Window ())windowSetLabel :: Window a -> String -> IO ()

frameCreate :: IO (Frame ())frameMaximize :: Frame a -> IO ()

Page 20: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

It works now

do f <- frameCreate windowSetLabel f "Hi"

f :: Frame () == Window (CFrame ()) == Ptr (CWindow (CFrame ()))

windowSetLabel :: Window a -> String -> IO ()

Page 21: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Properties

How can we model the "property" methods?

windowGetLabel :: Window a -> IO StringwindowSetLabel :: Window a -> String -> IO ()

windowGetLayout :: Window a -> IO LayoutwindowSetLayout :: Window a -> Layout -> IO ()

..

Page 22: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Get/Set

We would like to have generic "get" and "set" functions:

get :: w -> Attr -> IO aset :: w -> Attr -> a -> IO ()

Page 23: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Typed get/set

get :: w -> Attr w a -> IO aset :: w -> Attr w a -> a -> IO ()

text :: Attr (Window a) String

Page 24: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Attributes

data Attr w a = Attr (w -> IO a) (w -> a -> IO ())

text :: Attr (Window a) Stringtext = Attr windowGetLabel windowSetLabel

Page 25: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Generic get/set

get :: w -> Attr w a -> IO aget w (Attr getter setter) = getter w

set :: w -> Attr w a -> a -> IO ()set w (Attr getter setter) x = setter w x

Page 26: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Problems

I would like to set many "properties" at once:

set frame text "hi"set frame size (sz 300 300)set frame color blue

== (?)

map (set frame) [text "hi", size (sz 300 300), color blue]

Page 27: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Properties

Properties save a value/attribute pair.

data Prop w = Prop (w -> IO ())

prop :: Attr w a -> a -> Prop wprop (Attr getter setter) x = Prop (\w -> setter w x)

set :: w -> [Prop w] -> IO ()set w props = mapM_ setprop props where setprop (Prop setter) = setter w

Page 28: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Now we can set many properties

set frame [prop text "hi" ,prop color blue ,prop size (sz 300 300) ]

Page 29: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Problem

I want a nicer notation:

prop text "hi" text := "hi"

Page 30: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Existentials

data Prop w = (:=) (Attr w a) a

data Prop w = forall a. (:=) (Attr w a) a

Page 31: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

New definition of "set"

set :: w -> [Prop w] -> IO ()set w props = mapM_ setprop props where setprop ((Attr getter setter) := x) = setter w x

Page 32: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Definition of "frame"

frame :: [Prop (Frame ())] -> IO (Frame ())frame props = do f <- frameCreate idAny "" rectNull 0 set f props return f

Page 33: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

A combinator language for layout

set f [layout := margin 10 (column 5 [floatCentre (label "Hello") ,floatCentre (widget quit) ] ) ]

Page 34: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Example: C++ vs. Combinators

f <- frame [text "Demo"]

ok <- button f [text "Ok"]can <- button f [text "Cancel"]txt <- textCtrl f AlignLeft [clientSize := sz 100 60]

set f [layout := margin 10 $ column 10 [ fill $ widget txt , hfill $ row 10 [widget ok, widget can] ] ]

Page 35: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Abstract data type

data Layout

windowSetLayout :: Window a -> Layout -> IO ()

do f <- frameCreate idAny "Test" rectNull 0 ok <- buttonCreate f idAny "Bye" rectNull 0 windowSetLayout f (widget ok)

Page 36: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Primitives

widget :: Window a -> Layoutlabel :: String -> Layoutspace :: Size -> Layout

Page 37: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Containers

grid :: Int -> Int -> [[Layout]] -> Layout

grid 5 5 [[label "x", widget xinput] ,[label "y", widget yinput]]

Page 38: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Containers 2

row :: Int -> [Layout] -> Layoutcolumn :: Int -> [Layout] -> Layout

row n xs = grid n 0 [xs]

column n xs = grid 0 n (map (\x -> [x]) xs)

column 5 [grid 5 5 [[label "x", widget xinput] ,[label "y", widget yinput]] row 5 [widget ok, widget cancel]]

Page 39: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Attributes

margin :: Int -> Layout -> Layout

align :: Align -> Layout -> Layoutshaped :: Layout -> Layoutexpand :: Layout -> Layout

Page 40: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Stretch

hstretch, vstretch, stretch :: Layout -> Layout

stretch = hstretch . vstretch

column 5 $[grid 5 5 [[label "x", hstretch $ expand $ widget xinput] ,[label "y", hstretch $ expand $ widget yinput]],stretch $ alignBottomRight $ row 5 [widget ok, widget cancel]]

Page 41: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Many helpers

fill = stretch . expandhfill = hstretch . expand

floatBottomRight = stretch . alignBottomRight

empty = space (sz 0 0)glue = fill emptyhglue = hfill empty

Page 42: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Implementation

data Layout = Widget (Window ()) | Label String | Grid Int Int [[Layout]]

Page 43: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Transformers

data Layout = Widget { options :: Options, ..} | Label { options :: Options, ..} | Grid { options :: Options, ..}

data Options = Options{ stretchH :: Bool , stretchV :: Bool , marginW :: Int , .. }

Page 44: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Generate Layout

widget w = Widget defaultOptions wlabel s = Label defaultOptions s

hstretch layout = updateOptions (\opt -> opt { stretchH = True }) layout

updateOptions f layout = layout{ options = f (options layout) }

Page 45: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Translate Layout

windowSetLayout :: Window a -> Layout -> IO ()windowSetLayout w (Label options s) = do lab <- staticTextCreate s sizer <- windowSizerCreate lab (flags options) windowAddSizer w sizer..

flags options = (if stretchH options then wxHSTRETCH else 0) + (if stretchV options then wxVSTRETCH else 0) + ..

Page 46: WxHaskell Daan Leijen. Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag af kunt hebben en presenteren? Doaitse On donderdag, september.

Assignment: Turtle graphics

Design and implement an embedding of the LOGO language in Haskell.

Motivate your design decisions! Deadline: this Sunday.

http://wxhaskell.sourceforge.net/assignment.html [email protected]