wx Haskell Daan Leijen Ok Dat lijkt me

  • Slides: 46
Download presentation
wx. Haskell Daan Leijen

wx. Haskell Daan Leijen

Ok…. Dat lijkt me een goed plan. Denk je dat je zo iets dinsdag

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 volgens mij goed te doen met wx. Haskell -- behalve dan dat het geinstalleerd dient te worden. Als je wilt kunnen we misschien wat details afspreken en dat ik dan wat help om de opdracht vorm te geven met 1) een werkend voorbeeld, en 2) concrete vragen.

Overview l wx. Haskell as a concrete example of FFI, phantom types, existential types,

Overview l wx. Haskell as a concrete example of FFI, phantom types, existential types, combinator design, inheritance simulation, and IO as first -class values. l Homework: implement a "turtle" graphics combinator library.

wx. Haskell l wx. Haskell is a portable GUI library for Haskell build upon

wx. Haskell l wx. Haskell is a portable GUI library for Haskell build upon the wx. Windows (C++) library. l Two layers: a "core" binding (WXCore) and a haskellized layer (WX).

Hello world hello : : IO () hello = do f <- frame [text

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

Layout combinators set f [layout : = margin 10 (column 5 [float. Centre (label

Layout combinators set f [layout : = margin 10 (column 5 [float. Centre (label "Hello") , float. Centre (widget quit) ] ) ]

Demo

Demo

What is needed? l l l Foreign Function Interface (FFI) Model inheritance Create abstractions:

What is needed? l l l Foreign Function Interface (FFI) Model inheritance Create abstractions: – – Layout combinators Properties (get/set)

FFI l What are the primitives that you need to interface to the imperative

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

4 primitive operations are needed. 1. 2. 3. 4. Call the outside world (foreign

4 primitive operations are needed. 1. 2. 3. 4. Call the outside world (foreign import) Be called (foreign export) Use foreign data (CInt, Addr) Export haskell data (Stable. Ptr a)

Examples: foreign import sin : : Double -> IO Double foreign import strlen :

Examples: foreign import sin : : Double -> IO Double foreign import strlen : : Addr -> IO CInt

Phantom types l Make "Addr" typesafe: type Ptr a = Addr foreign import strlen

Phantom types l Make "Addr" typesafe: type Ptr a = Addr foreign import strlen : : Ptr Char -> IO Int

Abstraction foreign import strlen : : Ptr Char -> IO Int str. Len :

Abstraction foreign import strlen : : Ptr Char -> IO Int str. Len : : String -> Int str. Len s = unsafe. Perform. IO $ with. CString s $ cstr -> strlen cstr

Abstraction with. CString : : String -> (Ptr Char -> IO a) -> IO

Abstraction with. CString : : String -> (Ptr Char -> IO a) -> IO a with. CString s f = do p <- malloc (length s+1) map. M_ (poke p) (zip s [0. . ]) x <- f p free p return x

wx. Haskell window. Set. Label : : Window a -> String -> IO ()

wx. Haskell window. Set. Label : : Window a -> String -> IO () window. Set. Label w txt = with. CString txt $ cstr -> prim. Window. Set. Label w txt foreign import "window. Set. Label" prim. Window. Set. Label : : Window a -> Ptr Char -> IO ()

Inheritance l How to model inheritance? class Window { void set. Label( const char*

Inheritance l How to model inheritance? class Window { void set. Label( const char* txt ); . . }; class Frame : public Window { void maximize( void ); . . };

Simple model. type Window = Ptr CWindow data CWindow = CWindow type Frame =

Simple model. type Window = Ptr CWindow data CWindow = CWindow type Frame = Ptr CFrame data CFrame = CFrame window. Create : : IO Window window. Set. Label : : Window -> String -> IO () frame. Create : : IO Frame frame. Maximize : : Frame -> IO ()

Conversions? window. From. Frame : : Frame -> Window do f <- frame. Create

Conversions? window. From. Frame : : Frame -> Window do f <- frame. Create window. Set. Label (window. From. Frame f)

Encode inheritance in phantom type Window a = Ptr (CWindow a) data CWindow a

Encode inheritance in phantom type Window a = Ptr (CWindow a) data CWindow a = CWindow type Frame a = Window (CFrame a) data CFrame a = CFrame window. Create : : IO (Window ()) window. Set. Label : : Window a -> String -> IO () frame. Create : : IO (Frame ()) frame. Maximize : : Frame a -> IO ()

It works now do f <- frame. Create window. Set. Label f "Hi" f

It works now do f <- frame. Create window. Set. Label f "Hi" f : : Frame () == Window (CFrame ()) == Ptr (CWindow (CFrame ())) window. Set. Label : : Window a -> String -> IO ()

Properties l How can we model the "property" methods? window. Get. Label : :

Properties l How can we model the "property" methods? window. Get. Label : : Window a -> IO String window. Set. Label : : Window a -> String -> IO () window. Get. Layout : : Window a -> IO Layout window. Set. Layout : : Window a -> Layout -> IO (). .

Get/Set l We would like to have generic "get" and "set" functions: get :

Get/Set l We would like to have generic "get" and "set" functions: get : : w -> Attr -> IO a set : : w -> Attr -> a -> IO ()

Typed get/set get : : w -> Attr w a -> IO a set

Typed get/set get : : w -> Attr w a -> IO a set : : w -> Attr w a -> IO () text : : Attr (Window a) String

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

Attributes data Attr w a = Attr (w -> IO a) (w -> a -> IO ()) text : : Attr (Window a) String text = Attr window. Get. Label window. Set. Label

Generic get/set get : : w -> Attr w a -> IO a get

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

Problems l I would like to set many "properties" at once: set frame text

Problems l I would like to set many "properties" at once: set frame text "hi" set frame size (sz 300) set frame color blue == (? ) map (set frame) [text "hi", size (sz 300), color blue]

Properties l Properties save a value/attribute pair. data Prop w = Prop (w ->

Properties l Properties save a value/attribute pair. data Prop w = Prop (w -> IO ()) prop : : Attr w a -> Prop w prop (Attr getter setter) x = Prop (w -> setter w x) set : : w -> [Prop w] -> IO () set w props = map. M_ setprops where setprop (Prop setter) = setter w

Now we can set many properties set frame [prop text "hi" , prop color

Now we can set many properties set frame [prop text "hi" , prop color blue , prop size (sz 300) ]

Problem l I want a nicer notation: prop text "hi" text : = "hi"

Problem l I want a nicer notation: prop text "hi" text : = "hi"

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

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

New definition of "set" set : : w -> [Prop w] -> IO ()

New definition of "set" set : : w -> [Prop w] -> IO () set w props = map. M_ setprops where setprop ((Attr getter setter) : = x) = setter w x

Definition of "frame" frame : : [Prop (Frame ())] -> IO (Frame ()) frame

Definition of "frame" frame : : [Prop (Frame ())] -> IO (Frame ()) frame props = do f <- frame. Create id. Any "" rect. Null 0 set f props return f

A combinator language for layout set f [layout : = margin 10 (column 5

A combinator language for layout set f [layout : = margin 10 (column 5 [float. Centre (label "Hello") , float. Centre (widget quit) ] ) ]

Example: C++ vs. Combinators f <- frame [text "Demo"] ok <- button f [text

Example: C++ vs. Combinators f <- frame [text "Demo"] ok <- button f [text "Ok"] can <- button f [text "Cancel"] txt <- text. Ctrl f Align. Left [client. Size : = sz 100 60] set f [layout : = margin 10 $ column 10 [ fill $ widget txt , hfill $ row 10 [widget ok, widget can] ] ]

Abstract data type data Layout window. Set. Layout : : Window a -> Layout

Abstract data type data Layout window. Set. Layout : : Window a -> Layout -> IO () do f <- frame. Create id. Any "Test" rect. Null 0 ok <- button. Create f id. Any "Bye" rect. Null 0 window. Set. Layout f (widget ok)

Primitives widget : : Window a -> Layout label : : String -> Layout

Primitives widget : : Window a -> Layout label : : String -> Layout space : : Size -> Layout

Containers grid : : Int -> [[Layout]] -> Layout grid 5 5 [[label "x",

Containers grid : : Int -> [[Layout]] -> Layout grid 5 5 [[label "x", widget xinput] , [label "y", widget yinput]]

Containers 2 row : : Int -> [Layout] -> Layout column : : Int

Containers 2 row : : Int -> [Layout] -> Layout column : : 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]]

Attributes margin : : Int -> Layout align : : Align -> Layout shaped

Attributes margin : : Int -> Layout align : : Align -> Layout shaped : : Layout -> Layout expand : : Layout -> Layout

Stretch hstretch, vstretch, stretch : : Layout -> Layout stretch = hstretch. vstretch column

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 $ align. Bottom. Right $ row 5 [widget ok, widget cancel]]

Many helpers fill = stretch. expand hfill = hstretch. expand float. Bottom. Right =

Many helpers fill = stretch. expand hfill = hstretch. expand float. Bottom. Right = stretch. align. Bottom. Right empty = space (sz 0 0) glue = fill empty hglue = hfill empty

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

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

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

Transformers data Layout = Widget { options : : Options, . . } | Label { options : : Options, . . } | Grid { options : : Options, . . } data Options = Options{ stretch. H : : Bool , stretch. V : : Bool , margin. W : : Int , . . }

Generate Layout widget w = Widget default. Options w label s = Label default.

Generate Layout widget w = Widget default. Options w label s = Label default. Options s hstretch layout = update. Options (opt -> opt { stretch. H = True }) layout update. Options f layout = layout{ options = f (options layout) }

Translate Layout window. Set. Layout : : Window a -> Layout -> IO ()

Translate Layout window. Set. Layout : : Window a -> Layout -> IO () window. Set. Layout w (Label options s) = do lab <- static. Text. Create s sizer <- window. Sizer. Create lab (flags options) window. Add. Sizer w sizer. . flags options = (if stretch. H options then wx. HSTRETCH else 0) + (if stretch. V options then wx. VSTRETCH else 0) + . .

Assignment: Turtle graphics l l l Design and implement an embedding of the LOGO

Assignment: Turtle graphics l l l Design and implement an embedding of the LOGO language in Haskell. Motivate your design decisions! Deadline: this Sunday. http: //wxhaskell. sourceforge. net/assignment. html daan@cs. uu. nl