4

Is an OCaml function of signature:

'a -> 'b

possible?

I think it might be possible, however, I would not know the underlying logic behind the answer, so having it explained would be great :)

EDIT: It cannot recursively loop forever

pkiller162
  • 352
  • 1
  • 11

4 Answers4

9

There are several "legitimate" answers. One is to loop forever, which you ruled out:

let rec f x = f x

Another is to diverge by raising an exception or terminating the program:

let f x = exit 0

let f x = assert false

let f x = failwith "die"
gsg
  • 9,167
  • 1
  • 21
  • 23
0

It is possible using this:

let rec x = fun y -> x y;;

I'm not sure how it exactly works. I know x would have type:

`a -> `b

and y would have type:

`a

so x:`a->`b y:`a would have type:

`b

The problem is that it seems to go into an infinite loop.

Syed Jafri
  • 184
  • 6
  • 1
    Typing this into the toplevel gives Error: Unbound value b. I assume you cannot use the function inside itself without making it recursive? In which case it will loop forever. Whats intresting is the List.map function has signature ('a -> 'b)... – pkiller162 Nov 23 '14 at 03:38
  • 1
    Is it possible for their to exist a function which doesnt use recursion? Or use recursion which doesn't loop infinitely. – pkiller162 Nov 23 '14 at 03:49
  • I've been trying but I can't figure anything out so far. – Syed Jafri Nov 23 '14 at 03:52
0

There is Obj module, with Obj.magic function. And you can introduce function like magic, using external %identity primitive, like:

external magic : 'a -> 'b = "%identity"

But you must understand, that all this bypasses type system, and should be used at all. Without breaking type system, all functions of type 'a -> 'b share the same property - the do not return: so they should either raise an exception (or use other non-local exit) or do not return at all.

ivg
  • 34,431
  • 2
  • 35
  • 63
-1

Yes! There are various "trivial" ways to do it (by terminating the program, throwing an exception, or looping forever), but here is a very non-trivial method right from the standard library:

external magic: 'a -> 'b = "%identity"

Here, external is used to call C functions that use OCaml's C API. Normally, the string would be the name of the C function to call, but"%identity" is a compiler intrinsic that generates no code, but simply returns its argument. This takes advantage of the fact that OCaml simply trusts the type signatures given for external functions, as it cannot verify them.

It is part of the Obj module, where such low-level operations live, and is usually known by its fully qualified name, Obj.magic. It is an unsafe identity cast, as shown by the following:

        OCaml version 4.03.0+dev5-2014-10-15

# external magic: 'a -> 'b = "%identity";;
external magic : 'a -> 'b = "%identity"
# Printf.printf "%d\n" (magic 1);;
1
- : unit = ()
# (* Crash *) print_string (magic 1);;
[1]    4010 segmentation fault (core dumped)  ocaml

The segfault is because OCaml does not maintain type information at runtime. This cast is unchecked - the compiler/interpreter simply takes your word for it. The last example tries to dereference the internal representation of 1 (which is 0x3, due to the tag bit) as a pointer to a string, and that segfaults.

There are legitimate uses for this function, but they are rare. One set was in the Printf and Scanf sources, until a GADT-based solution was adopted. Other uses are in programs generated by Coq (which has a more powerful type system, and so can prove that casts are safe, even though OCaml can't). Other functions in the Obj module are sometimes used for hacks like mutating cons cells for tail-recursive list operations, and for avoiding indirections in extremely performance-critical code.

As a VERY good rule: If you are not absolutely sure that you should use the functions in the Obj module, or are not absolutely sure that such use is safe, don't. Using them is a good way to lead to heap corruption, which is both hard to debug and a security vulnerability that can lead to arbitrary code execution, judging by similar problems in C and C++ being exploitable.

Demi
  • 3,535
  • 5
  • 29
  • 45