Browse thread
Polymorphic variants question
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ 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