0
votes

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.

1
You can't return either just an int or a string. You'll have to wrap it in a variant, which is of course what you already have. The direct cause of the error, however, is that you specify int foo as the return type, when it's actually the argument type. There's really not much that makes sense about the code you've written. Perhaps if you provide a bit more context it would be possible to understand what you're actually trying to do. - glennsl
Sorry, I need to make a type inference engine and have literally never worked with Ocaml before lol. I made an edit to the post with the actual code I'm working with - Christian Bouwense
I don't see what the issue is with your actual code. If bar is supposed to represent infer_type, the latter returns a string in each branch, so no problem there. - glennsl
so if you compile that code it complains that string_of_typing_judgement is undefined, so I took it out temporarily. You're saying taking that out could be causing the issue, since when it's in both branches return a string? I don't really understand how pattern matching works, is it that string_of_typing_judgement takes on the value of whatever the wildcard matched? And if so, then it will resolve to a string applied to a typing_judgement, which doesn't make sense to me. (Again, sorry for the ignorant questions, I have no experience with Ocaml whatsoever). - Christian Bouwense
string_of_typing_judgement is used as a function here, being given a typing_judgement (tj). And by the name of it I'd say it's supposed to transform the typing_judgement into a string, which happens to work out well since the other branch returns a string as well. If the function is undefined, I guess that means you're supposed to implement it yourself. You also might want to pick up a book on the language, because these are pretty basic language concepts and you only seem to confuse yourself more by making flawed assumptions about them. - glennsl

1 Answers

1
votes

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.