* Question on Variant Types
@ 2006-06-28 16:27 Seth J. Fogarty
2006-06-28 16:47 ` [Caml-list] " Jonathan Roewen
2006-06-29 21:27 ` Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types) Richard Jones
0 siblings, 2 replies; 9+ messages in thread
From: Seth J. Fogarty @ 2006-06-28 16:27 UTC (permalink / raw)
To: caml-list
[-- Attachment #1: Type: text/plain, Size: 1903 bytes --]
I have a situation in which I have two kinds of trees. The simplified
example is linked lists:
type foo = [`Nil | `Tree of foo]
type bar = [`Nil | `Leaf of int | `Tree of bar]
I have a tree with only shape, and a tree with some information. I want to
be able to distinguish between these. Here I have functions to assert
types, but these annotations will be part of the signatures of functions
actually doing things in the real code. But I do want to have these static
checks on contests.
let f x : foo = x
let g x : bar = x
let a = `Tree (`Nil)
let b = `Tree (a)
let c = `Tree (f a)
let d = `Tree (`Leaf 1)
As is proper, I can run f on a, b, and c, but not on d. D is not a valid
foo.
But I cannot run g on c. This makes sense, as I have said 'a tree of bars
contains a bars.' But I want to somehow note that a tree of bars MIGHT
contain foo's. Is there any way to annotate this?
I cannot say
type bar = [`Nil | `Leaf of int | `Tree of [bar | foo]] as bar is not fully
defined.
I cannot say
type bar = [`Leaf of int | `Tree of bar | foo] because tree cannot have two
separate types.
The current, icky, non-variant type solution has the equivalent of
type 'a foo = Nil | Tree of foo | F of 'a
With special things filling in for 'a. But I end up putting EVERYTHING in 'a
because I don't have a way to statically guaranteeing that my "leaf foo"'s
are valid "leaf or branch foo's". So I have a weaker system than I want.
Any suggestions? Seems like variant types should work here. I COULD add type
annotations to functions, check them, and then remove the annotations so
that my types are never constrained. I think that might even work. But it
seems rather icky.
--
Seth Fogarty sfogarty@[gmail.com|rice.edu|livejournal]
Neep-neep at large AIM: Sorrath
"I know there are people in this world who do not love their fellow
human beings - and I hate people like that" --Tom Lehrer.
[-- Attachment #2: Type: text/html, Size: 2162 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
2006-06-28 16:27 Question on Variant Types Seth J. Fogarty
@ 2006-06-28 16:47 ` Jonathan Roewen
2006-06-28 16:48 ` Jonathan Roewen
2006-06-29 21:27 ` Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types) Richard Jones
1 sibling, 1 reply; 9+ messages in thread
From: Jonathan Roewen @ 2006-06-28 16:47 UTC (permalink / raw)
To: Seth J. Fogarty; +Cc: caml-list
> type foo = [`Nil | `Tree of foo]
> type bar = [`Nil | `Leaf of int | `Tree of bar]
>
> let f x : foo = x
> let g x : bar = x
> let a = `Tree (`Nil)
> let b = `Tree (a)
> let c = `Tree (f a)
> let d = `Tree (`Leaf 1)
>
> As is proper, I can run f on a, b, and c, but not on d. D is not a valid
> foo.
> But I cannot run g on c. This makes sense, as I have said 'a tree of bars
> contains a bars.' But I want to somehow note that a tree of bars MIGHT
> contain foo's. Is there any way to annotate this?
>From the ocaml reference docs:
# let bar_of_foo t = (t : foo :> bar);;
val bar_of_foo : foo -> bar = <fun>
# g (bar_of_foo c);;
- : bar = `Tree (`Tree `Nil)
Jonathan
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
2006-06-28 16:47 ` [Caml-list] " Jonathan Roewen
@ 2006-06-28 16:48 ` Jonathan Roewen
2006-06-28 23:44 ` Seth J. Fogarty
0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Roewen @ 2006-06-28 16:48 UTC (permalink / raw)
To: Seth J. Fogarty; +Cc: caml-list
> # let bar_of_foo t = (t : foo :> bar);;
> val bar_of_foo : foo -> bar = <fun>
> # g (bar_of_foo c);;
> - : bar = `Tree (`Tree `Nil)
I should've added that without needing an intermediate function, you
can also do:
g (c : foo :> bar);;
>
> Jonathan
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
2006-06-28 16:48 ` Jonathan Roewen
@ 2006-06-28 23:44 ` Seth J. Fogarty
2006-06-28 23:51 ` Jonathan Roewen
0 siblings, 1 reply; 9+ messages in thread
From: Seth J. Fogarty @ 2006-06-28 23:44 UTC (permalink / raw)
Cc: caml-list
[-- Attachment #1: Type: text/plain, Size: 584 bytes --]
Followup question:
Given I have:
type foo = [`A | `B of int | `C of char]
type bar = [`B of int | `C of char| `D]
and a function
let f (x : foo) : bar =
match x with
`A -> `D
|`B _
|`C _ -> (x : bar)
Is there any way to properly coerce this using the restricted variant
information of x? Or do I have to duplicate code and reconstruct x?
--
Seth Fogarty sfogarty@[gmail.com|rice.edu|livejournal]
Neep-neep at large AIM: Sorrath
"I know there are people in this world who do not love their fellow
human beings - and I hate people like that" --Tom Lehrer.
[-- Attachment #2: Type: text/html, Size: 787 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
2006-06-28 23:44 ` Seth J. Fogarty
@ 2006-06-28 23:51 ` Jonathan Roewen
[not found] ` <c7ee61120606281739g27fc344bt855cde4bd6a89797@mail.gmail.com>
0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Roewen @ 2006-06-28 23:51 UTC (permalink / raw)
To: Seth J. Fogarty; +Cc: caml-list
> Followup question:
> Given I have:
> type foo = [`A | `B of int | `C of char]
> type bar = [`B of int | `C of char| `D]
>
> and a function
> let f (x : foo) : bar =
> match x with
> `A -> `D
> |`B _
> |`C _ -> (x : bar)
>
> Is there any way to properly coerce this using the restricted variant
> information of x? Or do I have to duplicate code and reconstruct x?
let f (x : foo) : bar = match x with
| `A -> `D
| `B _ | `C _ as x -> (x : bar)
Jonathan
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
[not found] ` <c7ee61120606281739g27fc344bt855cde4bd6a89797@mail.gmail.com>
@ 2006-06-29 3:09 ` Jonathan Roewen
2006-06-29 3:37 ` Jacques Garrigue
1 sibling, 0 replies; 9+ messages in thread
From: Jonathan Roewen @ 2006-06-29 3:09 UTC (permalink / raw)
To: Seth J. Fogarty; +Cc: OCaml
On 6/29/06, Seth J. Fogarty <sfogarty@gmail.com> wrote:
> If you have time, I have one more question I can't seem to solve. Which
> quite possibly has as simple an answer as the other two. You've been very
> helpful so far, and I don't want to impose, so feel free to let me know if
> you've not the time.
>
> type foo = [`A of int | `B | 'D of foo]
> type bar = [`A of int | `C of foo * bar | 'D of bar]
>
> let rec occurs i x =
> match x with
> |`A j -> i = j
> |`C (foo, bar) -> (occurs i foo) or (occurs i bar)
> |_ -> false
>
> I would like occurs to work on bars and foos. But as it is, occurs won't
> work on either, because it assigns the `C variant the type "`C of 'b * 'b".
> Even if I spell out `D and `B, I cannot get it to accept. Nor does:
>
> let rec occurs i (x : 'a) =
> match x with
> |`A j -> i = j
> |`C ((foo : foo), (bar : bar)) ->
> (occurs i (foo : foo :> 'a) or
> (occurs i (bar : bar :> 'a)))
> |_ -> false
>
> even compile.
>
> let rec occurs i x =
> match x with
> |`A j -> i = j
> |(`C (foo, bar) : bar) -> (occurs i foo) or (occurs i bar)
> |_ -> false
>
> has similar problems.
>
> Again, any assistance would be greatly appreciated, but is not necessary.
Only thing I could think of was:
# let rec occurs i = function
| `A j -> i = j
| `C (f,b) -> (occurs_foo i f) || (occurs_bar i b)
| otherwise -> false
and occurs_foo i = function
| `A j -> i = j
| otherwise -> false
and occurs_bar i = function
| `A j -> i = j
| `C (f,b) -> (occurs_foo i f) || (occurs_bar i b)
| otherwise -> false;;
val occurs :
'a ->
[> `A of 'a
| `C of ([> `A of 'a ] as 'b) * ([> `A of 'a | `C of 'b * 'c ] as 'c) ] ->
bool = <fun>
val occurs_foo : 'a -> [> `A of 'a ] -> bool = <fun>
val occurs_bar :
'a -> ([> `A of 'a | `C of [> `A of 'a ] * 'b ] as 'b) -> bool = <fun>
# occurs 2 (`C ((`D (`B)), (`C (`A 3, (`D (`C (`A 4, `A 2)))))));;
- : bool = false
Basically specialising on the two types. There may be a way to coerce
them to not need it, but I'm not sure what it is.
Here are two other solutions:
# let rec occurs i x =
let map = function
| `A j -> `A j
| `C (f,b) -> print_endline "C"; `C (f,b)
| x -> `None
in match map x with
| `A j -> i = j
| `None -> false
| `C (f,b) -> (occurs i f) or (occurs i b);;
val occurs : 'a -> ([> `A of 'a | `C of 'b * 'b ] as 'b) -> bool = <fun>
--
# let occurs i x =
let map = function
| `A _ | `C (_,_) as x -> x | _ -> `None
in
let rec occurs = function
| `A j -> i = j
| `C (f,b) -> (occurs (map f)) or (occurs (map b))
| `None -> false
in occurs x;;
val occurs :
'a ->
[ `A of 'a
| `C of
([> `A of 'a | `C of 'b * ([> `A of 'a | `C of 'b * 'c ] as 'c) ] as 'b) *
'c
| `None ] -> bool = <fun>
Pretty damn ugly! But it works... Perhaps someone more proficient with
variant types on the list can come up with a more reasonable solution
than my hack ;-)
Jonathan
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question on Variant Types
[not found] ` <c7ee61120606281739g27fc344bt855cde4bd6a89797@mail.gmail.com>
2006-06-29 3:09 ` Jonathan Roewen
@ 2006-06-29 3:37 ` Jacques Garrigue
1 sibling, 0 replies; 9+ messages in thread
From: Jacques Garrigue @ 2006-06-29 3:37 UTC (permalink / raw)
To: Seth J. Fogarty; +Cc: caml-list
On 6/29/06, Seth J. Fogarty <sfogarty@gmail.com> wrote:
> If you have time, I have one more question I can't seem to solve. Which
> quite possibly has as simple an answer as the other two. You've been very
> helpful so far, and I don't want to impose, so feel free to let me know if
> you've not the time.
>
> type foo = [`A of int | `B | 'D of foo]
> type bar = [`A of int | `C of foo * bar | 'D of bar]
>
> let rec occurs i x =
> match x with
> |`A j -> i = j
> |`C (foo, bar) -> (occurs i foo) or (occurs i bar)
> |_ -> false
>
> I would like occurs to work on bars and foos. But as it is, occurs won't
> work on either, because it assigns the `C variant the type "`C of 'b * 'b".
> Even if I spell out `D and `B, I cannot get it to accept.
As long as foo and bar are two subtypes of a common type, you can
still solve the problem by defining that type and using subtyping:
type foobar = [`A of int | `B | `C of foobar * foobar | `D of foobar]
let occurs_foo i x = occurs i (x : foo :> foobar)
let occurs_bar i x = occurs i (x : bar :> foobar)
Jacques Garrigue
^ permalink raw reply [flat|nested] 9+ messages in thread
* Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types)
2006-06-28 16:27 Question on Variant Types Seth J. Fogarty
2006-06-28 16:47 ` [Caml-list] " Jonathan Roewen
@ 2006-06-29 21:27 ` Richard Jones
2006-06-29 21:51 ` Jonathan Roewen
1 sibling, 1 reply; 9+ messages in thread
From: Richard Jones @ 2006-06-29 21:27 UTC (permalink / raw)
To: caml-list
I have another question on variant types which seems to be related to
this, but perhaps the opposite way round. How can I get the code
below to work? (It's simplified greatly from a real problem I'm
having).
Rich.
----------------------------------------------------------------------
type colour = [ `Red | `Green | `Blue ]
type colour' = [ colour | `Default ]
type instructions = Set_foreground of colour' | Set_background of colour'
let default_fg : colour = `Red
let default_bg : colour = `Green
let process_instructions =
List.fold_left (
fun (fg, bg) ->
function
| Set_foreground `Default ->
let new_fg = default_fg in
(new_fg, bg)
| Set_foreground new_fg ->
(new_fg, bg)
| Set_background `Default ->
let new_bg = default_bg in
(fg, new_bg)
| Set_background new_bg ->
(fg, new_bg)
)
let string_of_colour = function
| `Red -> "red"
| `Green -> "green"
| `Blue -> "blue"
let () =
let instrs =
[ Set_foreground `Blue; Set_background `Red; Set_foreground `Default ] in
let fg, bg = `Green, `Blue in
let fg, bg = process_instructions (fg, bg) instrs in
print_endline ("fg = " ^ string_of_colour fg);
print_endline ("bg = " ^ string_of_colour bg)
----------------------------------------------------------------------
--
Richard Jones, CTO Merjis Ltd.
Merjis - web marketing and technology - http://merjis.com
Team Notepad - intranets and extranets for business - http://team-notepad.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types)
2006-06-29 21:27 ` Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types) Richard Jones
@ 2006-06-29 21:51 ` Jonathan Roewen
0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Roewen @ 2006-06-29 21:51 UTC (permalink / raw)
To: Richard Jones; +Cc: caml-list
Hi,
You just need some type constraints so it knows you're starting with a
colour pair, not a colour' pair:
let process_instructions (initial:colour * colour) =
List.fold_left (
fun (fg, bg) ->
function
| Set_foreground `Default ->
let new_fg = default_fg in
(new_fg, bg)
| Set_foreground (#colour as new_fg) ->
(new_fg, bg)
| Set_background `Default ->
let new_bg = default_bg in
(fg, new_bg)
| Set_background (#colour as new_bg) ->
(fg, new_bg)
) initial
Jonathan
On 6/30/06, Richard Jones <rich@annexia.org> wrote:
> I have another question on variant types which seems to be related to
> this, but perhaps the opposite way round. How can I get the code
> below to work? (It's simplified greatly from a real problem I'm
> having).
>
> Rich.
>
> ----------------------------------------------------------------------
> type colour = [ `Red | `Green | `Blue ]
> type colour' = [ colour | `Default ]
> type instructions = Set_foreground of colour' | Set_background of colour'
>
> let default_fg : colour = `Red
> let default_bg : colour = `Green
>
> let process_instructions =
> List.fold_left (
> fun (fg, bg) ->
> function
> | Set_foreground `Default ->
> let new_fg = default_fg in
> (new_fg, bg)
> | Set_foreground new_fg ->
> (new_fg, bg)
> | Set_background `Default ->
> let new_bg = default_bg in
> (fg, new_bg)
> | Set_background new_bg ->
> (fg, new_bg)
> )
>
> let string_of_colour = function
> | `Red -> "red"
> | `Green -> "green"
> | `Blue -> "blue"
>
> let () =
> let instrs =
> [ Set_foreground `Blue; Set_background `Red; Set_foreground `Default ] in
> let fg, bg = `Green, `Blue in
> let fg, bg = process_instructions (fg, bg) instrs in
> print_endline ("fg = " ^ string_of_colour fg);
> print_endline ("bg = " ^ string_of_colour bg)
> ----------------------------------------------------------------------
>
> --
> Richard Jones, CTO Merjis Ltd.
> Merjis - web marketing and technology - http://merjis.com
> Team Notepad - intranets and extranets for business - http://team-notepad.com
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2006-06-29 21:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-28 16:27 Question on Variant Types Seth J. Fogarty
2006-06-28 16:47 ` [Caml-list] " Jonathan Roewen
2006-06-28 16:48 ` Jonathan Roewen
2006-06-28 23:44 ` Seth J. Fogarty
2006-06-28 23:51 ` Jonathan Roewen
[not found] ` <c7ee61120606281739g27fc344bt855cde4bd6a89797@mail.gmail.com>
2006-06-29 3:09 ` Jonathan Roewen
2006-06-29 3:37 ` Jacques Garrigue
2006-06-29 21:27 ` Another question on variant types and matching (was: Re: [Caml-list] Question on Variant Types) Richard Jones
2006-06-29 21:51 ` Jonathan Roewen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox