caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Problem correlating input and output type
@ 2010-01-31 18:01 Goswin von Brederlow
  2010-01-31 19:28 ` [Caml-list] " Tiphaine Turpin
  0 siblings, 1 reply; 4+ messages in thread
From: Goswin von Brederlow @ 2010-01-31 18:01 UTC (permalink / raw)
  To: caml-list

Hi,

last night I had a crazy idea for a better GUI framework.

In a GUI you have objects that react to events (being clicked, being
dragged, covered/uncovered, resized ...). Oftent basic objects
(e.g. buttons) are then combined to build higher level objects
(e.g. dialog boxes). Each object now has their own set of events that it
handles internally and events that need to be reacted to by some
callback. For example a dialog box redraws itself when resized. But
clicking on "ok" needs to be handled outside the dialog box. If any
event remains unanswered that is usualy a bad thing. You click at "ok"
and nothing happens. Not good.

Now my crazy idea was that the type of an object should include the
events lacking a callback. I simplified this to a mutable bool that
needs to be set true.

Method 1: polymorphic variants
------------------------------

# type 'a t = { mutable foo : bool; mutable bla : bool; mutable bar : bool }
  let make () =
    ({ foo = false; bla = false; bar = false; } : [`Foo | `Bla | `Bar] t);;
type 'a t = { mutable foo : bool; mutable bla : bool; mutable bar : bool; }
val make : unit -> [ `Bar | `Bla | `Foo ] t = <fun>

The make method gives a totaly unconnected object that still needs Foo,
Bla and Bar set.

# let (set_foo : [> `Foo ] t -> [> ] t) =
  function x -> x.foo <- true; x;;
val set_foo : ([> `Foo ] as 'a) t -> 'a t = <fun>

# set_foo (make ());;
- : [ `Bar | `Bla | `Foo ] t = {foo = true; bla = false; bar = false}

As you can see the type correlation that the output type no longer
contains `Foo doesn't work. I would like the type to be like this:

  let (set_foo : [ `Foo | 'a ] t -> [ 'a ] t) =
    function x -> x.foo <- true; x;;


Method 2: polymorphic types
---------------------------

# type 'a foo
  type 'a bla
  type 'a bar
  type 'a t = { mutable foo : bool; mutable bla : bool; mutable bar : bool }
  let make () =
    ({ foo = false; bla = false; bar = false; } : unit foo bla bar t);;
type 'a foo
type 'a bla
type 'a bar
type 'a t = { mutable foo : bool; mutable bla : bool; mutable bar : bool; }
val make : unit -> unit foo bla bar t = <fun>

# let (set_foo : 'a foo 'b -> 'a 'b) = function x -> x.foo := true; x;;

Unfortunately the 'b isn't allowed in that position.


Method 3: labeled arguments
---------------------------

# type t = { mutable foo : bool; mutable bla : bool; mutable bar : bool }
  let make ~foo ~bla ~bar = { foo = foo; bla = bla; bar = bar };;
type t = { mutable foo : bool; mutable bla : bool; mutable bar : bool; }
val make : foo:bool -> bla:bool -> bar:bool -> t = <fun>

# let set_foo x = x ~foo:true
  let set_bla x = x ~bla:true
  let set_bar x = x ~bar:true;;
val set_foo : (foo:bool -> 'a) -> 'a = <fun>
val set_bla : (bla:bool -> 'a) -> 'a = <fun>
val set_bar : (bar:bool -> 'a) -> 'a = <fun>

# set_foo make;;
- : bla:bool -> bar:bool -> t = <fun>

# set_bar (set_bla (set_foo make));;
- : t = {foo = true; bla = true; bar = true}

# make ~bla:true;;
- : foo:bool -> bar:bool -> t = <fun>

# (make ~bla:true) ~bar:true;;
- : foo:bool -> t = <fun>

That looks good so far. BUT

# set_bla make;;
Error: This expression has type foo:bool -> bla:bool -> bar:bool -> t
       but an expression was expected of type bla:bool -> 'a

While I can use the labeled in any order on the original function that
does not translate to parameter passing.



Can anyone think of a way to express this so that the type system keeps
track of which callbacks are already connected?

MfG
        Goswin


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Problem correlating input and output type
  2010-01-31 18:01 Problem correlating input and output type Goswin von Brederlow
@ 2010-01-31 19:28 ` Tiphaine Turpin
  2010-02-01 15:59   ` Goswin von Brederlow
  0 siblings, 1 reply; 4+ messages in thread
From: Tiphaine Turpin @ 2010-01-31 19:28 UTC (permalink / raw)
  To: Goswin von Brederlow; +Cc: caml-list

Goswin von Brederlow a écrit :
> Hi,
>
> last night I had a crazy idea
Definitely :-).

> [...]
>
>
> Can anyone think of a way to express this so that the type system keeps
> track of which callbacks are already connected?
>   
Here is an attempt (with only two "events"). Note that :
- the imperative version cannot prevent connecting a signal more than once
- such types can only represent sets of "parallel" edges of a lattice,
i.e., this doesn't generalises to arbitrary "typestate" properties
- this is just a curiosity, and not a reasonable way of doing such
things. Runtime checking would be much easier (but still a bit hackish).

Tiphaine

module LatticeFun : sig

  type ('foo, 'bar) r
  type t and f

  val make : unit -> (f, f) r
  val set_foo : (f, 'bar) r -> (t, 'bar) r
  val set_bar : ('foo, f) r -> ('foo, t) r
  val use : (t, t) r -> unit

end = struct

  type ('foo, 'bar) r = {foo : bool ; bar : bool}

  type t
  type f = t

  let make () = {foo = false ; bar = false}
  let set_foo x = {x with foo = true}
  let set_bar x = {x with bar = true}
  let use _ = ()

end

module LatticeImp : sig

  type ('foo, 'bar) r
  type t and f

  val make : unit -> (f, f) r
  val set_foo : ('foo, 'bar) r -> (t, 'bar) r
  val set_bar : ('foo, 'bar) r -> ('foo, t) r
  val use : (t, t) r -> unit

end = struct

  (* for some reason, the direct declaration causes a module type error *)
  type r1 = {mutable foo : bool ; mutable bar : bool}
  type ('foo, 'bar) r = r1

  type t
  type f = t

  let make () = {foo = false ; bar = false}
  let set_foo x = x.foo <- true ; x
  let set_bar x = x.bar <- true ; x
  let use _ = ()

end



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Problem correlating input and output type
  2010-01-31 19:28 ` [Caml-list] " Tiphaine Turpin
@ 2010-02-01 15:59   ` Goswin von Brederlow
  2010-02-01 22:12     ` Tiphaine Turpin
  0 siblings, 1 reply; 4+ messages in thread
From: Goswin von Brederlow @ 2010-02-01 15:59 UTC (permalink / raw)
  To: Tiphaine Turpin; +Cc: Goswin von Brederlow, caml-list

Tiphaine Turpin <Tiphaine.Turpin@irisa.fr> writes:

> Goswin von Brederlow a écrit :
>> Hi,
>>
>> last night I had a crazy idea
> Definitely :-).
>
>> [...]
>>
>>
>> Can anyone think of a way to express this so that the type system keeps
>> track of which callbacks are already connected?
>>   
> Here is an attempt (with only two "events"). Note that :
> - the imperative version cannot prevent connecting a signal more than once
> - such types can only represent sets of "parallel" edges of a lattice,
> i.e., this doesn't generalises to arbitrary "typestate" properties
> - this is just a curiosity, and not a reasonable way of doing such
> things. Runtime checking would be much easier (but still a bit hackish).

But runtime checks will only show the error when the GUI object is
instantiated. Some obscure dialog might not pop up in month.

> Tiphaine
>
> module LatticeFun : sig
>
>   type ('foo, 'bar) r
>   type t and f
>
>   val make : unit -> (f, f) r
>   val set_foo : (f, 'bar) r -> (t, 'bar) r
>   val set_bar : ('foo, f) r -> ('foo, t) r
>   val use : (t, t) r -> unit
>
> end = struct
>
>   type ('foo, 'bar) r = {foo : bool ; bar : bool}
>
>   type t
>   type f = t
>
>   let make () = {foo = false ; bar = false}
>   let set_foo x = {x with foo = true}
>   let set_bar x = {x with bar = true}
>   let use _ = ()
>
> end
>
> module LatticeImp : sig
>
>   type ('foo, 'bar) r
>   type t and f
>
>   val make : unit -> (f, f) r
>   val set_foo : ('foo, 'bar) r -> (t, 'bar) r
>   val set_bar : ('foo, 'bar) r -> ('foo, t) r
>   val use : (t, t) r -> unit
>
> end = struct
>
>   (* for some reason, the direct declaration causes a module type error *)
>   type r1 = {mutable foo : bool ; mutable bar : bool}
>   type ('foo, 'bar) r = r1
>
>   type t
>   type f = t
>
>   let make () = {foo = false ; bar = false}
>   let set_foo x = x.foo <- true ; x
>   let set_bar x = x.bar <- true ; x
>   let use _ = ()
>
> end

Thanks. That solves the first problem. But how do you translate that
into ocaml objects?

type need_click
type have_click

class type ['click] clickable_type = object
  method set_click : ...?
  method use : ...?
end

I believe a method can not change the type of a class nor can it require
the parametereized class to be of a certain type. And if I write helper
function outside the class like

let set_foo x = x#foo <- true ; x

then I can't use inheritance for them. Maybe I can use inheritance
for the class objects and module inclusion for the set_* helpers. But
how do I write the use function so that one can not use of an inherited
class?

Or how do I specify

method add_connected_obj : (<connected>) obj

The <connected> would need to be specific to the exact type of object
being added. I do believe I need something that simplifies the type with
each aplication of a callback so that all fully connected objects will
have the same basic type, e.g.

unit need_click need_drag obj => unit need_click obj => unit obj

MfG
        Goswin


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Problem correlating input and output type
  2010-02-01 15:59   ` Goswin von Brederlow
@ 2010-02-01 22:12     ` Tiphaine Turpin
  0 siblings, 0 replies; 4+ messages in thread
From: Tiphaine Turpin @ 2010-02-01 22:12 UTC (permalink / raw)
  To: Goswin von Brederlow; +Cc: caml-list

Goswin von Brederlow a écrit :
> Tiphaine Turpin <Tiphaine.Turpin@irisa.fr> writes:
>
>   
>> Goswin von Brederlow a écrit :
>>     
>>> [...]
>>>
>>> Can anyone think of a way to express this so that the type system keeps
>>> track of which callbacks are already connected?
>>>   
>> Runtime checking would be much easier (but still a bit hackish).
>>     
>
> But runtime checks will only show the error when the GUI object is
> instantiated. Some obscure dialog might not pop up in month.
[...]
> But how do you translate that into ocaml objects?
>
>   
I see two requirements in your problem that are difficult to combine:
- static checking by an "ordinary" type system
- dynamic connection of objects.

First, I believe that it prevents anything imperative (because such
typing ignores the execution flow). A functional approach may succeed in
some sense, but I don't think that it would be practical. As for the
combination with objects, In my (humble) experience with objects in
Ocaml, I found that typing even reasonably simple designs is not a
trivial task. So, combining that with the earlier hack would quickly
become a nightmare.

My personal opinion would be to drop the second condition, and make the
connection of your objects static. I would try to define the objects as
functors, with one module parameter per connection, and connect all that
using (possibly recursive) module definitions.

I'm curious to know what solutions object-oriented people could propose,
in particular with dependency injection.

Tiphaine


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-02-01 22:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-31 18:01 Problem correlating input and output type Goswin von Brederlow
2010-01-31 19:28 ` [Caml-list] " Tiphaine Turpin
2010-02-01 15:59   ` Goswin von Brederlow
2010-02-01 22:12     ` Tiphaine Turpin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).