Christian Bouwense
Christian Bouwense

Reputation: 165

Ocaml Pattern Matching User Defined Type

I am trying to write a function which can either return an int or a string, based on the result of a call to a function baz.

type 'a foo = OK of 'a | Error of string

let bar (e) : int foo =
    match baz e with
    | OK (_) -> 1
    | Error s -> s

However, I get this error message when compiling:

Error: This expression has type int but an expression was expected of type
         int foo
Command exited with code 2.

What exactly am I doing wrong here?

EDIT: Here's the actual snippet of code I'm dealing with:

type 'a error = | OK of 'a | Error of string

type typing_judgement = subst*expr*texpr


let rec infer' (e:expr) (n:int): (int*typing_judgement) error =
    match e with
    | _ -> failwith "infer': undefined"


let infer_type (AProg e) =
    match infer' e 0 with
    | OK (_, tj) -> string_of_typing_judgement tj
    | Error s -> "Error! "^ s

The end goal here is a type inference engine, so as I can tell infer_type will be given an expression, which will be passed to infer' (which I will have to implement). I've never worked with Ocaml before and I'm just trying to get this to compile before I even attempt to implement these functions.

Upvotes: 0

Views: 2806

Answers (1)

William Leiserson
William Leiserson

Reputation: 155

From your initial code, it looks like the function wants to be:

let bar e =

(In general, let OCaml infer the type of e) That said, when you get a result back of Ok or Error, this is the variant you're looking for (as glennsl says). At that point, you can report the Error or return some result. For example:

let bar e =
    match baz e with
    | Ok _ -> ()
    | Error s ->
        let () = prerr_endline ("Error: " ^ s) in
        exit 1

The Ok case returns void in my example, since your code didn't seem concerned about the contents of Ok, but you could simply return that instead:

| Ok result -> result

Again, OCaml will infer all the types, so there's no need to be explicit like you would be in C/C++.

As to the actual code: failwith will throw an exception. Apart from the "infer" function cleanup, "infer_type" could look something like this:

let infer_type expr =
    try string_of_typing_judgment @@ infer expr
    with Failure msg -> 
        let () = prerr_endline ("Infer failed with: " ^ msg) in
        exit 1

The @@ is just a handy operator that avoids the need for parentheses. It means the same as:

string_of_typing_judgment (infer expr)

But the overall paradigm, here, when using failwith, is exception handling. If you're expecting an exception, use the "try/with" syntax.

Finally, I'd recommend running through a couple of quickstart tutorials on OCaml before starting your project. A lot of this will get cleared up pretty quickly once you have some worked examples.

Upvotes: 1

Related Questions