Version française
Home     About     Download     Resources     Contact us    
Browse thread
Polymorphic variants question
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Jon Harrop <jon@f...>
Subject: Re: [Caml-list] Polymorphic variants question
On Friday 01 September 2006 18:31, David Allsopp wrote:
> let f x = if x = `A then (true, `B) else (false, x);;

You probably want:

# let f = function `A -> true, `B | `C -> false, `C;;
val f : [< `A | `C ] -> bool * [> `B | `C ] = <fun>

> then I get a type error unless I change
> 	(false, x)
> to
> 	(false, id x)

Use coercion :> instead of an ad-hoc function:

# let (f : [`A | `C] -> bool * [`A | `B | `C]) =
    fun x -> if x = `A then (true, `B) else (false, (x :> [`A|`B|`C]));;
val f : [ `A | `C ] -> bool * [ `A | `B | `C ] = <fun>

> Is there a better way of writing this? I'm using this in the context of
> several interrelated lexers where `A, `B and `C are high-level states and
> certain lexers can only be called in a subset of those states but each
> lexer may yield any value for the next-state. I'd quite like to eliminate
> the id x bit since it's only there to "separate" x from the return value
> for the type-checker.

Note that the type of your id function is not 'a -> 'a:

# let id = function `A -> `A | `C -> `C;;
val id : [< `A | `C ] -> [> `A | `C ] = <fun>

So it accepts a subset of {A, C} and returns a type that unifies with any 
superset of {A, C}.

To leverage static type checking you must provide as much information as 
possible to the static type checker. In this case, rather than using "if" to 
denote `A or not `A, you can just as easily use pattern matching to imply 
specifically `A or `C.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists