I am making a turtle graphics program by using ocaml. And this requires to provide an implementation of the module conforming to the following OCaml signature.
type program
type ins
val mf: float -> ins
val mb: float -> ins
val tl: float -> ins
val tr: float -> ins
val pu: ins
val pd: ins
val repeat: int -> program -> ins
val make_program: ins list -> program
type stroke
val strokes: program -> stroke list
type state
val animate: program -> state list
val strokes': program -> unit
val animate': program -> unit
Define a type for turtle programs and for turtle instructions.
The mf, mb, tl, tr, pu, pd, repeat and make_program functions are
used to build instructions and programs.
Define a type for strokes.
Program a function strokes that, given a turtle program, returns the
list of the strokes drawn by the turtle.
Define a type for the state of the turtle.
Program a function animate that, given a turtle program, returns the
list of states of the turtle.
The strokes' and animate' render the strokes and turtle animation
This is my code for mf, pu and pd:
type turtle = {
mutable x : float;
mutable y : float;
mutable phi : float;
mutable stt : int;
}
let round = int_of_float
let pi = 3.1415926535897932384626433832795
let rad_of_deg a = a *. pi /. 180.
let p = { x = 100.; y = 100.; phi = 0.; stt = 1 }
let pu() =
p.stt <- 0
let pd() =
p.stt <- 1
let mf l =
let x2 = (p.x) +. l *. cos (rad_of_deg p.phi)
and y2 = (p.y) +. l *. sin (rad_of_deg p.phi) in
moveto (round p.x) (round p.y);
if (p.stt == 1) then lineto (round x2) (round y2);
p.x <- x2;
p.y <- y2
The output of mf is:
val mf: float -> unit = <fun>
My question is how to make it look like the requirements?
I will try to give you a few hints, but you should consider to learn OCaml textbooks. I'm not going to teach you OCaml in a few keystrokes, not because I don't want to, but because it is impossible.
In OCaml a compilation unit consists of two parts:
module implementation
module signature
Module implementation consists of values and types, and each value has a type, associated with it. OCaml will infer types for values for you, but you can help it, using type annotations.
The implementation should be put in a file that has extension .ml. Signature should be put in a file with .mli extension. OCaml compiler will take them both, if they share the same name and build a compilation unit for you, that can be later linked into an executable.
For example you can put the given above signature into the file named gr.mli. Then you need to write a file that will implement this interface. You must name this file gr.ml and put your types and values into it. Then you can compile it using
ocamlbuild gr.cmo
and OCaml compiler will check whether your implementation actually implements the given signature. In order to conform to the signature, your module should contain all the values and types, specified in the signature and their types should be the same. Indeed, your implementation can contain more values, and types of values can be more general, than what is specified in a signature, but we're going to far away.
What you're showing in your example, (I'm refering to val mf: float -> unit = <fun>) is actually the output of the OCaml toplevel interpreter. And it consists of three parts (I use capital letter to denote that this is a variable part of the pattern):
val NAME : TYPE = VALUE
where NAME is a name of a value (in your case it is mf), TYPE is its inferred type (float -> unit in your case), and VALUE is a printable representation of the value. Since functions doesn't have a printable representation it is denoted as <fun> in your case. You can compare the type of your definition with the type of required definition (i.e., float -> ins). It isn't very hard to guess that this types can be equal if type ins is equal to type unit. Whether it is true depends on your implementation.
I hope, that this will help you. But this is not instead of reading textbooks. I'm just trying to give you starting hints.
Related
I'd like make a Set module containing functions. But there seems to be no way to compare functions, which Set needs. This obvious-looking thing compiles:
module Action = struct
type t = unit -> unit
let compare : t -> t -> int = Stdlib.compare
end
module Actions = Set.Make(Action)
But if I attempt to use it:
Fatal error: exception Invalid_argument("compare: functional value")
I just want compare that the functions are the same object, I am not trying to do something silly like compare them for equal behaviour.
Am I supposed to use something from the Obj module here?
The semantics of Stdlib.compare is to look arbitrarily deep inside the objects to see how their subparts compare. This doesn't really work for functions, as you point out. So OCaml doesn't allow compare to be applied to functions.
There isn't really a useful order that can be applied to functions, even if you're willing to use physical equality. Function values are immutable and can be duplicated or moved physically by the runtime system, at least in theory.
Since the ordering would necessarily be arbitrary, you can get the same effect by making your own arbitrary order: pair the functions with an int value that increases monotonically as you create new pairs.
Add an identity to your actions, e.g., you can compare actions by name,
module Action = struct
type t = {
name : string;
func : (unit -> unit);
}
let compare x y = String.compare x.name y.name
end
You should also ensure that all actions have different names, for example by introducing a global hash table that records all created actions. Make sure that actions are only creatable via the Action module, by adding an appropriate signature.
OCaml Stdlib compare documentation states ...
val compare : 'a -> 'a -> int
compare x y returns 0 if x is equal to y, a negative integer if x is less than y, and a positive integer if x is greater than y. The ordering implemented by compare is compatible with the comparison predicates =, < and > defined above, with one difference on the treatment of the float value nan. Namely, the comparison predicates treat nan as different from any other float value, including itself; while compare treats nan as equal to itself and less than any other float value. This treatment of nan ensures that compare defines a total ordering relation.
compare applied to functional values may raise Invalid_argument. compare applied to cyclic structures may not terminate.
The compare function can be used as the comparison function required by the Set.Make and Map.Make functors, as well as the List.sort and Array.sort functions.
Now we have two notion(s) of equality in OCaml, namely...
Structural Equality: Expressed using operator =, the type of which is
# (=);;
- : 'a -> 'a -> bool = <fun>
Physical Equality: Expressed using operator ==, the type of which is
# (==);;
- : 'a -> 'a -> bool = <fun>
As we can see, the type of both is same, but the function application of both of them is different when it comes to function value as arguments.
Structural Equality doesn't hold over function values, but Physical Equality may. Trying to compare(as in =) with function values throws. And as stated in the documentation of Stdlib.compare, it uses structural equality.
Illustration: Structural Equality with Function Values
# let f x = x;;
val f : 'a -> 'a = <fun>
# let g x = x;;
val g : 'a -> 'a = <fun>
# f = g;;
Exception: Invalid_argument "compare: functional value".
# g = f;;
Exception: Invalid_argument "compare: functional value".
Illustration: Physical Equality with Function Values
# let f x = x;;
val f : 'a -> 'a = <fun>
# let g x = x;;
val g : 'a -> 'a = <fun>
# f == g;;
- : bool = false
# f == f;;
- : bool = true
# g == g;;
- : bool = true
# g == f;;
- : bool = false
# let h x y = x + y;;
val h : int -> int -> int = <fun>
# h == f;;
Error: This expression has type int -> int
but an expression was expected of type int -> int -> int
Type int is not compatible with type int -> int
So in short, I don't think we can use Stdlib.compare with Set.Make with function values.
So ...
Either, we will have to keep the type t in Action module to something over which structural equality can be applied if we have to continue using Stdlib.compare.
Or, implement compare of your own so that it can do something with those function values as arguments, along with satisfying the function contract of val compare : t -> t -> int as mandated by Set.OrderedType module type.
WYSIWYG => WHAT YOU SHOW IS WHAT YOU GET
The OCaml type-checker infinite-loops on this example:
module type I =
sig
module type A
module F :
functor(X :
sig
module type A = A
module F : functor(X : A) -> sig end
end) -> sig end
end
module type J =
sig
module type A = I
module F : functor(X : I) -> sig end
end
(* Try to check J <= I *)
module Loop(X : J) = (X : I)
source: Andreas Rossberg adapting Mark Lillibridge's example
I don't have a good handle of how/why this works. In particular:
Is the example minimal?
What work are all the sharing constraints A = I, A = A, etc. doing? Are sharing constraints necessary in order to cause this infinite loop?
What work is the inline signature in the first functor doing? That seems to be essential to the example.
Is this trick useful only for infinite-looping, or can arbitrary computation happen in the module system?
Can examples like this be translated to other languages? Traits and classes with type members and parameterized type aliases look a lot like the code above.
The example is pretty minimal, it relies on two essential ingredients:
an abstract module type
a functor to make the abstract module type appear in both covariant and contravariant position.
Answering your high-level questions before going back to the example:
With this trick only the subtyping checker for the module type system is doing an unbounded amount of work. You cannot observe the result of this computation. However, using abstract module type is the key to trick the module type system into doing expansive computation (a module with a chain of 4↑↑4 submodule for instance)
Reproducing this exact problem probably requires both subtyping and impredicativity, I am not sure how often this combination appears outside of module systems.
Going back to the example at hand, I propose to leap a bit into the future with OCaml 4.13 and its with module type constraint. I hope that this makes the ingredients behind this trick a little bit more visible:
module type e = sig end
module type Ieq = sig
module type X
module type A = X
module F : X -> e
end
module type I = sig
module type A
module F : Ieq with module type X = A -> e
end
module type J = Ieq with module type X = I
Opinions may vary, but I find that this form makes it more obvious that in the I case, we have more equations on the functor F component, whereas in the Ieq with module type X = ... case, we have one more equation on the module type A component.
While trying to prove that J<I, we end up moving around those equations without achieving any progress. Let's try to see how that happens step by step.
First, we look at the module type A:
J
I
J.A = module type A = I
I.A = module type A (abstract)
Since I.A is abstract, this is true. Then, we need to compare J.F and I.F, but only after adding the equation A=I from J.
J
I with module type A = I
J.F = I -> e
I.F = (Ieq with module type X = (*A =*) I) -> e
Now, we have a functor. Functors are contravariant in their argument. In other words, to prove that X -> e < Y -> e, we need to prove that Y < X.
Thus, we need to prove that Ieq with module type X = I < I... but this inequation looks a bit familiar. And indeed, we had defined:
module type J = Ieq with module type X = I
Reusing this definitions, this means that we are back to trying to prove J<I, without making any progress.
If we look at our previous steps, the problem started when we extended I with another copy of itself I with module type A = I. Then contravariance allowed us to spread this increase of size to both side of the comparison. Therefore, our inclusion check is always producing more work for its future self and this specific inclusion check never ends.
I want to create database and table datatypes in OCaml. May I use 2 sig keywords in 1 module? Could you give an example of how to write a signature and how to implement it?
If you are referring to have a module that satisfies 2 module types, yes, you can.
module type ADDITIVE = sig
type t
val add : t -> t -> t
end
module type MULTIPLICATIVE = sig
type t
val multiply : t -> t -> t
end
module Number : sig
include ADDITIVE
include MULTIPLICATIVE with type t := t
end = struct
type t = int
let add x y = x + y
let multiply x y = x + y
end
We say the signature of module Number is the inclusion of module type ADDITIVE (that opens t in that context) and MULTIPLICATIVE with the same type in t of the t from ADDITIVE, so we can implement the module according to the signature.
I am currently working with OCaml, and I want to create some types which are somehow secured, in the sense that I want to select only those instances which satisly some properties.
The way that I found to acheive that is to encapsulate my type in a module, making it private, and defining the constructors in such a way that they check if the object that they are trying to make satisfy these properties. As my code is a bit long, I want to split into different modules, but my types are mutually recursive, so I am using recursive modules. I end up in the following situation (I simplified a lot so that it becomes readable)
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i x : t = B.checker i x; cons i x
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
But this code is rejected, with the following error message :
Characters 226-227:
let secured_cons i x = B.checker i x; cons i x
^
Error: This expression has type A.t but an expression was expected of type
t = int list
This looks to me very weird, because as we are in the context A, the two types t and A.t are supposed to be equal. From my understanding, what happens is that inside A, the type t is considered to be a synonym for int list whereas outside A, the signature tells us that it is private, so it is just a copy of this type, with a coercion A.t :> int list. The entire point is that there is no coercion the other way around, which is exactly why I want to use private type abbreviations
But in my case I am inside the module A, so I would like to use this extra information to say that my type t should coerce to A.t
Does anyone have a better explanation of why this error is happening, and how I could avoid it? (I have thought of switching to abstract types, but I get exactly the same error)
I have found a way to solve this issue I am posting it here in case anyone else ever encounters the same.
We just have to explicitly specify what types and coercion we expect from the system - here is my example slightly modified in a correct way :
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i (x:A.t) = B.checker i x; cons i (x :> t)
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
It might look silly to write let secured_cons i (x:A.t) inside the module A itself, but as far as I understand it, it is the only way to specify to the system that it should go out of the module to check the signature, and use the same type as the signature (so here a private type) instead of the internal type t which is still a synonymous for int list
I had more trickier cases, but this idea could be adapted to each of them, and helped me solve them all.
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
You're errors occur because when B.checker is invoked, x is infered as an A.t because of the signature of B.
You can see that easily if you explicitly type the secured_cons function :
let secured_cons i (x:t) : t = B.checker i x; cons i x
which now produces the symmetrical error:
let secured_cons i (x:t) = B.checker i x; cons i x
^
Error: This expression has type t = int list
but an expression was expected of type A.t
In fact you here have a real designing problem in my opinion. If you want the module B to check the values produced by the module A, so without surprise B must inspect in some way the type A.t. Having that type private makes it impossible.
From what i understand you have three options :
remove private
Add a browse, getter function that allows the B module to access the content of the values of type A.t
the way i would do this : put the checking function into the module A
I'd be glad to hear what more experienced users have to say about this, but here is my take on it.
I, as a developer, usually give a lot of importance to the semantics of a code. In your case, the B module is specifically used by the A module, and it has no other goal than that.
Thus, sticking to a nested module (even if it makes your code a bit longer) would be the way to go as far as I am concerned. There is no point is exposing the B module. Below is the refactored example to illustrate.
module A : sig
type t
val secured_cons : int -> t -> t
end = struct
type t = int list
module B : sig
val checker : int -> t -> unit
end = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end
And here is the signature of the module as given by utop:
module A : sig type t val secured_cons : int -> t -> t end
which is perfect in my sense because it only shows the interface to your module, and nothing of its implementation.
As a side-note, if you wanted to expose the signature of the B module (to give it to a functor, for example), just move it to the signature of the A module, as follows:
module A : sig
type t
val secured_cons : int -> t -> t
module B : sig
val checker : int -> t -> unit
end
end = struct
type t = int list
module B = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end;;
Here is the signature of the module as given by utop:
module A :
sig
type t
val secured_cons : int -> t -> t
module B : sig val checker : int -> t -> unit end
end
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
A private type abbreviation of the form type u = private t declares a type u that is distinct from the implementation type t. It is the same as declaring an abstract type with the following two exceptions:
compiler treats the type t, as an implementation type, that opens an avenue for optimizations - this, however, doesn't mean that a type checker considers them the same, for the type checker they are distinct.
typechecker allows a coercion of type u to type t.
So, from a typechecker perspective, these two types are distinct. As always in OCaml type discipline all coercions should be made explicit, and a subtype is not equal to a super type unless it is coerced. In your case, the typechecker is trying to unify type A.t = private int list with type int list since A.t and int list are distinct types, it is rejected. It is, however, allowed to coerce A.t to int list (but not the vice verse).
It might look silly to write let secured_cons i (x:A.t) inside the module A itself
You don't need to write it (at least in your simple example). Just using x :> t is enough.
I was wondering if it is possible to have compile-time check in OCaml to make sure arrays are the correct length. For my problem, I want to verify that two GPU 1-dim vectors are of the same length before doing piecewise vector subtraction.
let init_value = 1
let length = 10_000_000
let x = GpuVector.create length init_value and y = GpuVector.create 9 init_value in
let z = GpuVector.sub v1 v2
In this example I would like it to throw a compile error as x and y are not the same length. As I am a OCaml noob I would like to know how I can achieve this? I am guessing that I will have to use functors or camlp4 (which I have never used before)
You cannot define a type family in OCaml for arrays of length n where n can have arbitrary length. It is however possible to use other mechanisms to ensure that you only GpuVector.sub arrays of compatible lengths.
The easiest mechanism to implement is defining a special module for GpuVector of length 9, and you can generalise the 9 by using functors. Here is an example implementation of a module GpuVectorFixedLength:
module GpuVectorFixedLength =
struct
module type P =
sig
val length : int
end
module type S =
sig
type t
val length : int
val create : int -> t
val sub : t -> t -> t
end
module Make(Parameter:P): S =
struct
type t = GpuVector.t
let length = Parameter.length
let create x = GpuVector.create length x
let sub = GpuVector.sub
end
end
You can use this by saying for instance
module GpuVectorHuge = GpuVectorFixedLength.Make(struct let length = 10_000_000 end)
module GpuVectorTiny = GpuVectorFixedLength.Make(struct let length = 9 end)
let x = GpuVectorHuge.create 1
let y = GpuVectorTiny.create 1
The definition of z is then rejected by the compiler:
let z = GpuVector.sub x y
^
Error: This expression has type GpuVectorHuge.t
but an expression was expected of type int array
We therefore successfully reflected in the type system the property for two arrays of having the same length. You can take advantage of module inclusion to quickly implement a complete GpuVectorFixedLength.Make functor.
The slap library implements such kind of size static checks (for linear algebra).
The overall approach is described this abstract