wxhaskell daan leijen. ok…. dat lijkt me een goed plan. denk je dat je zo iets dinsdag af kunt...

46
wxHaskell Daan Leijen

Upload: christiana-edwards

Post on 17-Jan-2016

213 views

Category:

Documents


0 download

TRANSCRIPT

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]