caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Getting rid of impossible polymorphic variant tags from infered types
@ 2004-03-01 15:09 Florian Hars
  2004-03-01 16:35 ` Claudio Sacerdoti Coen
  0 siblings, 1 reply; 4+ messages in thread
From: Florian Hars @ 2004-03-01 15:09 UTC (permalink / raw)
  To: caml-list

If I write a function to filter out all occurences of values of a specific 
polymorphic variant tag from a list, ocaml infers a return type for this 
function of any type that may contain the tag I have just removed:

# let f l = List.filter (function `Fnord -> false | _ -> true) l;;
val f : ([> `Fnord] as 'a) list -> 'a list = <fun>

While I unterstand why this type is infered, it is nonetheless wrong, it should 
be something like [> 'a \ `Fnord ] list (inventing notation on the fly).
Is there some decent way to tell the compiler that I know more about this 
function than the type checker does?

The following should be safe, but doesn't strike me as especially elegant and 
makes the type more restrictive than I'd like it to be:

type foo = [ `Foo | `Bar | `Fnord ]
type foo_flat = [ `Foo | `Bar ]

let f' l =
   let f_r (v: foo) (init: foo_flat list) =
     match v with
     | `Fnord -> init
     | _ -> Obj.magic v :: init
   in
   List.fold_right f_r l []

Yours, Florian.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Getting rid of impossible polymorphic variant tags from infered types
  2004-03-01 15:09 [Caml-list] Getting rid of impossible polymorphic variant tags from infered types Florian Hars
@ 2004-03-01 16:35 ` Claudio Sacerdoti Coen
  2004-03-03 10:27   ` Florian Hars
  0 siblings, 1 reply; 4+ messages in thread
From: Claudio Sacerdoti Coen @ 2004-03-01 16:35 UTC (permalink / raw)
  To: caml-list

> type foo = [ `Foo | `Bar | `Fnord ]
> type foo_flat = [ `Foo | `Bar ]
> 
> let f' l =
>   let f_r (v: foo) (init: foo_flat list) =
>     match v with
>     | `Fnord -> init
>     | _ -> Obj.magic v :: init
>   in
>   List.fold_right f_r l []

 There is no need for Obj.magic:

type foo_flat = [ `Foo | `Bar ]
type foo = [ foo_flat | `Fnord ]
let f_r (v : foo) (init : foo_flat list) =
 match v with
   `Fnord -> init
 | #foo_flat as v -> v :: init
 ;;
type foo = [ `Bar | `Fnord | `Foo ]
type foo_flat = [ `Bar | `Foo ]
val f_r : foo -> foo_flat list -> foo_flat list

 Since the list `Foo | `Bar of variants is written only once,
 the code is also reasonably extensible. Of course it is still not
 what you want.




 If you really need to exclude the `Fnord value at compile time, an
 alternative solution is to use phantom types:

type 'a foo = [ `Foo | `Bar | `Fnord ]
let f_r (v : 'a foo) (init : ([> `NoFnord] foo) list) =
 match v with
   `Fnord -> init
 | _ -> v :: init
 ;;
type 'a foo = [ `Bar | `Fnord | `Foo ]
val f_r : 'a foo -> ([> `NoFnord ] as 'b) foo list -> 'b foo list

The `NoFnord variant explicitly tells that the Fnord value is not allowed.
Notice how the first parameter does not have to satisfy this restriction,
while the second one has to. As usual, you need to use modules to enforce
that a value of type `Foo has type [`NoFnord] foo whereas a value of type
`NoFnord has NOT type [`NoFnord].

					Regards,
					C.S.C.

-- 
----------------------------------------------------------------
Real name: Claudio Sacerdoti Coen
PhD Student in Computer Science at University of Bologna
E-mail: sacerdot@cs.unibo.it
http://www.cs.unibo.it/~sacerdot
----------------------------------------------------------------

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Getting rid of impossible polymorphic variant tags from infered types
  2004-03-01 16:35 ` Claudio Sacerdoti Coen
@ 2004-03-03 10:27   ` Florian Hars
  2004-03-03 10:40     ` Claudio Sacerdoti Coen
  0 siblings, 1 reply; 4+ messages in thread
From: Florian Hars @ 2004-03-03 10:27 UTC (permalink / raw)
  To: Claudio Sacerdoti Coen; +Cc: caml-list

Claudio Sacerdoti Coen wrote:
>  If you really need to exclude the `Fnord value at compile time, an
>  alternative solution is to use phantom types:
> 
> type 'a foo = [ `Foo | `Bar | `Fnord ]
> let f_r (v : 'a foo) (init : ([> `NoFnord] foo) list) =
>  match v with
>    `Fnord -> init
>  | _ -> v :: init
>  ;;

But this gives me the worst of both worlds, no? I have to define a function f_r 
for every type I might want to use in place of foo, *and* the type checker can 
still see the `Fnord that isn't there:

# let l' = List.fold_right f_r [`Fnord; `Foo; `Bar] [] ;;
val l' : _[> `NoFnord] foo list = [`Foo; `Bar]
# match List.hd l' with
   | `Foo -> print_endline "Foo!"
   | `Bar -> print_endline "Bar!";;
This pattern matches values of type [< `Bar | `Foo]
but is here used to match values of type
   [> `NoFnord] foo = [ `Bar | `Fnord | `Foo]
The first variant type does not allow tag(s) `Fnord

So the "| #foo_flat as v -> v :: init" version seems to be the only workable 
solution.

Yours, Florian.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Getting rid of impossible polymorphic variant tags from infered types
  2004-03-03 10:27   ` Florian Hars
@ 2004-03-03 10:40     ` Claudio Sacerdoti Coen
  0 siblings, 0 replies; 4+ messages in thread
From: Claudio Sacerdoti Coen @ 2004-03-03 10:40 UTC (permalink / raw)
  To: Florian Hars; +Cc: caml-list

> But this gives me the worst of both worlds, no?

 It is a bit heavyweight, but not too bad.

> I have to define a function 
> f_r for every type I might want to use in place of foo,

 Wasn't it your goal to define f_r in the first place?

> *and* the type checker can still see the `Fnord that isn't there:

 You are right here. Indeed, you should define your own case-analysis
 operator (whose principal argument would have type [> `NoFnord] foo)
 and use it in place of the match ... with.
 Withouth proper syntax sugar the code becomes clumsy.
 This is a drawback of phantom types.

> So the "| #foo_flat as v -> v :: init" version seems to be the only 
> workable solution.

					Regards,
					C.S.C.

-- 
----------------------------------------------------------------
Real name: Claudio Sacerdoti Coen
PhD Student in Computer Science at University of Bologna
E-mail: sacerdot@cs.unibo.it
http://www.cs.unibo.it/~sacerdot
----------------------------------------------------------------

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

end of thread, other threads:[~2004-03-03 10:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-01 15:09 [Caml-list] Getting rid of impossible polymorphic variant tags from infered types Florian Hars
2004-03-01 16:35 ` Claudio Sacerdoti Coen
2004-03-03 10:27   ` Florian Hars
2004-03-03 10:40     ` Claudio Sacerdoti Coen

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).