Multipying int64 types in OCAML - ocaml

I am attempting to multiply two int types in OCAML and I am not sure on what I might be doing wrong
let prime = Int64.of_string("0x100000002b2") in
let temp = ref prime in
hash := Int64.mul(!temp,prime);
I get the error
Error: This expression has type 'a * 'b
but an expression was expected of type int64
Any suggestions on how I can fix this ?
Update:
I got reference to this method from here
I am curious what this means
val mul : int64 -> int64 -> int64
Multiplication.
How do we know how many parameters this method takes ?

Function parameters in OCaml are (in the usual idiom) placed after the name of the function, with no parentheses and no comma.
# Int64.mul 8L 9L;;
- : int64 = 72L
Commas are used to create tuples, but Int64.mul doesn't accept a tuple. It accepts two separate arguments as above. (In FP parlance, it's a curried function.)
(It might be worth working through a short tutorial on OCaml. You seem to be assuming it's like traditional C family languages, but it's rather different.)
Update
The type x -> y is the type of a function that accepts a parameter of type x and returns a value of type y. The type x -> y -> z is the type of a (curried) function that takes two parameters of types x and y and returns a value of type z. (This is a somewhat simplified way of looking at things, but is close enough to get started with.)
So the function mul that you cite takes two parameters of type int64 and returns a value of type int64.
(I repeat my advice about an OCaml tutorial. It's really worth learning about the OCaml type system before getting too deep into coding.)

Related

OCaml Type Inferencing

I'm just starting to learn OCaml, and I was confused by how the OCaml compiler determines the input type of arguments in certain situations where the argument could be multiple types. I'm assuming I would need to explicitly state the type in these instances? For example:
let sign x =
if x > 0 then 1
else if x < 0 then -1
else 0
let _ = print_int(sign 1.5)
Throws "Error: This expression has type float but an expression was expected of type int"
But don't the comparison operators work with floats as well? Why does the compiler assume that the argument should be an int instead of saying something like the argument type is ambiguous (unless I'm mistaken and the type actually is not ambiguous)?
The built-in comparison operators in OCaml have the following type signature:
'a -> 'a -> bool. Note that while the argument types are generic ('a), they are both the same. So, when you have a comparison like x < 0, the compiler sees that the type of the second argument is int and then infer that the type of x must be int as well. Changing your comparisons to use floats, e.g. x < 0. will make your code type-check, but then it would no longer work for int inputs.

Do OCaml 'underscore types' (e.g. '_a) introduce the possibility of runtime type errors / soundness violations?

I was reading a little bit about the value restriction in Standard ML and tried translating the example to OCaml to see what it would do. It seems like OCaml produces these types in contexts where SML would reject a program due to the value restriction. I've also seen them in other contexts like empty hash tables that haven't been "specialized" to a particular type yet.
http://mlton.org/ValueRestriction
Here's an example of a rejected program in SML:
val r: 'a option ref = ref NONE
val r1: string option ref = r
val r2: int option ref = r
val () = r1 := SOME "foo"
val v: int = valOf (!r2)
If you enter the first line verbatim into the SML of New Jersey repl you get
the following error:
- val r: 'a option ref = ref NONE;
stdIn:1.6-1.33 Error: explicit type variable cannot be generalized at its binding declaration: 'a
If you leave off the explicit type annotation you get
- val r = ref NONE
stdIn:1.6-1.18 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val r = ref NONE : ?.X1 option ref
What exactly is this dummy type? It seems like it's completely inaccessible and fails to unify with anything
- r := SOME 5;
stdIn:1.2-1.13 Error: operator and operand don't agree [overload conflict]
operator domain: ?.X1 option ref * ?.X1 option
operand: ?.X1 option ref * [int ty] option
in expression:
r := SOME 5
In OCaml, by contrast, the dummy type variable is accessible and unifies with the first thing it can.
# let r : 'a option ref = ref None;;
val r : '_a option ref = {contents = None}
# r := Some 5;;
- : unit = ()
# r ;;
- : int option ref = {contents = Some 5}
This is sort of confusing and raises a few questions.
1) Could a conforming SML implementation choose to make the "dummy" type above accessible?
2) How does OCaml preserve soundness without the value restriction? Does it make weaker guarantees than SML does?
3) The type '_a option ref seems less polymorphic than 'a option ref. Why isn't let r : 'a option ref = ref None;; (with an explicit annotation) rejected in OCaml?
Weakly polymorphic types (the '_-style types) are a programming convenience rather than a true extension of the type system.
2) How does OCaml preserve soundness without the value restriction? Does it make weaker guarantees than SML does?
OCaml does not sacrifice value restriction, it rather implements a heuristic that saves you from systematically annotating the type of values like ref None whose type is only “weekly” polymorphic. This heuristic by looking at the current “compilation unit”: if it can determine the actual type for a weekly polymorphic type, then everything works as if the initial declaration had the appropriate type annotation, otherwise the compilation unit is rejected with the message:
Error: The type of this expression, '_a option ref,
contains type variables that cannot be generalized
3) The type '_a option ref seems less polymorphic than 'a option ref. Why isn't let r : 'a option ref = ref None;; (with an explicit annotation) rejected in OCaml?
This is because '_a is not a “real” type, for instance it is forbidden to write a signature explicitly defining values of this “type”:
# module A : sig val table : '_a option ref end = struct let option = ref None end;;
Characters 27-30:
module A : sig val table : '_a option ref end = struct let option = ref None end;;
^^^
Error: The type variable name '_a is not allowed in programs
It is possible to avoid using these weakly polymorphic types by using recursive declarations to pack together the weakly polymorphic variable declaration and the later function usage that completes the type definition, e.g.:
# let rec r = ref None and set x = r := Some(x + 1);;
val r : int option ref = {contents = None}
val set : int -> unit = <fun>
1) Could a conforming SML implementation choose to make the "dummy" type above accessible?
The revised Definition (SML97) doesn't specify that there be a "dummy" type; all it formally specifies is that the val can't introduce a polymorphic type variable, since the right-hand-side expression isn't a non-expansive expression. (There are also some comments about type variables not leaking into the top level, but as Andreas Rossberg points out in his Defects in the Revised Definition of Standard ML, those comments are really about undetermined types rather than the type variables that appear in the definition's formalism, so they can't really be taken as part of the requirements.)
In practice, I think there are four approaches that implementations take:
some implementations reject the affected declarations during type-checking, and force the programmer to specify a monomorphic type.
some implementations, such as MLton, prevent generalization, but defer unification, so that the appropriate monomorphic type can become clear later in the program.
SML/NJ, as you've seen, issues a warning and instantiates a dummy type that cannot subsequently be unified with any other type.
I think I've heard that some implementation defaults to int? I'm not sure.
All of these options are presumably permitted and apparently sound, though the "defer unification" approach does require care to ensure that the type doesn't unify with an as-yet-ungenerated type name (especially a type name from inside a functor, since then the monomorphic type may correspond to different types in different applications of the functor, which would of course have the same sorts of problems as a regular polymorphic type).
2) How does OCaml preserve soundness without the value restriction? Does it make weaker guarantees than SML does?
I'm not very familiar with OCaml, but from what you write, it sounds like it uses the same approach as MLton; so, it should not have to sacrifice soundness.
(By the way, despite what you imply, OCaml does have the value restriction. There are some differences between the value restriction in OCaml and the one in SML, but none of your code-snippets relates to those differences. Your code snippets just demonstrate some differences in how the restriction is enforced in OCaml vs. one implementation of SML.)
3) The type '_a option ref seems less polymorphic than 'a option ref. Why isn't let r : 'a option ref = ref None;; (with an explicit annotation) rejected in OCaml?
Again, I'm not very familiar with OCaml, but — yeah, that seems like a mistake to me!
To answer the second part of your last question,
3) [...] Why isn't let r : 'a option ref = ref None;; (with an explicit annotation) rejected in OCaml?
That is because OCaml has a different interpretation of type variables occurring in type annotations: it interprets them as existentially quantified, not universally quantified. That is, a type annotation only has to be right for some possible instantiation of its variables, not for all. For example, even
let n : 'a = 5
is totally valid in OCaml. Arguably, this is rather misleading and not the best design choice.
To enforce polymorphism in OCaml, you have to write something like
let n : 'a. 'a = 5
which would indeed cause an error. However, this introduces a local quantifiers, so is still somewhat different from SML, and doesn't work for examples where 'a needs to be bound elsewhere, e.g. the following:
fun pair (x : 'a) (y : 'a) = (x, y)
In OCaml, you have to rewrite this to
let pair : 'a. 'a -> 'a -> 'a * 'a = fun x y -> (x, y)

Why is the binding of the functor result with a new module name required to call nested functor of initial functor?

I have:
module Functor(M : sig end) = struct
module NestedFunctor(M : sig end) = struct
end
end
This code is valid:
module V = Functor(struct end)
module W = V.NestedFunctor(struct end)
But this is invalid:
module M = Functor(struct end).NestedFunctor(struct end)
(* ^ Error: Syntax error *)
As I understand, a functor is a relation between a set of input modules and a set of possible output modules. But this example confuses my understanding. Why is the binding of the functor result with a new module name required to call nested functor of initial functor?
My compiler version = 4.01.0
I'm new to OCaml. When I found functors I imagined something as
Engine.MakeRunnerFor(ObservationStation
.Observe(Matrix)
.With(Printer))
I thought it is a good tool for the human-friendly architecture notation.
Then I was disappointed. Of course, this is a syntax error and I understand that. But I think this restriction inflates grammar and makes it less intuitive. And my "Why?" in the main question is in the context of the concept of language.
While I don't believe that this restriction is strictly necessary, it is probably motivated by certain limitations in OCaml's module type system. Without going into too much technical detail, OCaml requires all intermediate module types to be expressible as syntactic signatures. But with functors, that sometimes isn't possible. For example, consider:
module Functor(X : sig end) = struct
type t = T of int
module Nested(Y : sig end) = struct let x = T 5 end
end
Given this definition, the type of the functor Functor(struct end).Nested can't be expressed in OCaml syntax. It would need to be something like
functor(Y : sig end) -> sig val x : Functor(struct end).t end (* not legal OCaml! *)
but Functor(struct end).t isn't a valid type expression in OCaml, for reasons that are rather technical (in short, allowing a type like that would make deciding what types are equal -- as necessary during type checking -- much more involved).
Naming intermediate modules often avoids this dilemma. Given
module A = Functor(struct end)
the functor A.Nested has type
functor(Y : sig end) -> sig val x : A.t end
by referring to the named intermediate result A.
Using the terminology in the manual, types and the like (module types, class types, etc.) can be qualified by an extended-module-path where a qualifier can be a functor call, whereas non-types (core expressions, module expressions, classes, etc.) can only be qualified by a module-path where qualifiers have to be plain module names.
For example, you can write a type Functor(struct end).NestedFunctor(struct end).t but not an expression Functor(struct end).NestedFunctor(struct end).x or a module expression Functor(struct end).NestedFunctor(struct end).
Syntax-wise, allowing extended-module-path in expressions would be ambiguous: the expression F(M).x is parsed as the constructor F applied to the expression (M).x, where M is a constructor and the . operator is the record field access operator. This won't ever typecheck since M is obviously a variant to which the . operator can't be applied, but eliminating this at the parser would be complicated. There may be other ambiguities I'm not thinking of right now (with first-class modules?).
As far as the type checker is concerned, functor calls in types designation isn't a problem — they're allowed. However the argument has to itself be a path: you can write Set.Make(String).t but not Set.Make(struct type t = string let compare = … end).t. Allowing structures and first-class modules in type expressions would make the type checker more complex, because of the way OCaml manages abstract types. Every time you write Set.Make(String).t, it designates the same abstract type; but if you write
module M1 = Set.Make(struct type t let compare = String.compare end)
module M2 = Set.Make(struct type t let compare = String.compare end)
then M1 and M2 are distinct abstract types. The technical way to formulate this is that in OCaml, functor application is applicative: applying the same functor to the same argument always returns the same abstract type. But structures are generative: writing struct … end twice produces distinct abstract types — so Set.Make(struct type t let compare = String.compare end).t ≠ Set.Make(struct type t let compare = String.compare end).t — generative types lead to a non-reflexive equality between type expressions if you aren't careful what you allow in type expressions.
Code generation wouldn't be impacted much, because it could desugar Functor(struct … end).field as let module TMP = struct … end in Functor(TMP).field.
As far as I can see, there's no deep answer. The reported error is a syntax error. I.e., the grammar of OCaml just doesn't support this notation.
One way to summarize it is that in the grammar for a module expression, the dot always appears as part of a "long module identifier", i.e., between two capitalized identifiers. I checked this just now, and that's what I saw.

Frequency Trees

I am currently revising for my programming exam (I am new at programming) and I came across with an exercise asking me to implement a functions which "take a frequency tree and list of bits to a value in the Frequency tree and return the remaining bits in a list".
the part that i have trouble understanding is the type that I was given:
FreqTree a -> [bit] -> (a,[bit])
what does the (a, [bit]) actually mean? is a just a value?
Thanks heaps
The type (a, b) is a tuple or pair containing both an a and a b. In Haskell lowercase types are actually type variables, or unknowns. If they are written in a type then it means that the type is invariant to the actual type that variable represents.
If we read the description of this function carefully we can see it is reflective of the type:
take a frequency tree and list of bits to a value in the Frequency tree and return the remaining bits in a list
A function type like
a -> b -> c
can be read as a function from an a and a b to a c. In fact, to further cement the notion of and we had before we can write an equivalent function of type
(a, b) -> c
repeating the idea that tuple types should be read as "and". This conversion is called curry
curry :: (a -> b -> c) -> ((a, b) -> c)
curry f (a, b) = f a b
Using this notion, the description of the function translates to
(FreqTree, ListOfBits) -> (ValueInFreqTree, ListOfRemainingBits)
take
a frequency tree *and* list of bits
to
a value in the Frequency tree *and* the remaining bits in a list
From here we just do a little pattern matching against the type given
(FreqTree , ListOfBits) -> (ValueInFreqTree, ListOfRemainingBits)
FreqTree -> ListOfBits -> (ValueInFreqTree, ListOfRemainingBits)
FreqTree a -> [bit] -> (a , [bit] )
The first step above is the opposite of curry, called uncurry, and the second step compares our expected type to the type given. Here we can see some good parity—list of bits map to [bit] and FreqTree maps to FreqTree a.
So the final bit is to figure out how that type variable a works. This requires understanding the meaning of the parameterized type FreqTree a. Since frequency trees might contain any type of thing caring not about its particular form and only about the ability to compute its frequency, it's nice to parameterize the type by it's value. You might write
FreqTree value
where, again, the lowercase name represents a type variable. In fact, we can do this substitution in the previous type as well, value for a
FreqTree value -> [bit] -> (value, [bit])
and now perhaps this type has taken its most clear form. Given a FreqTree containing unknown types marked as value and a list of bit, we return a particular value and another list of bit.

OCaml type of the plus operator

Why is the type of a plus ( + ) considered to be int -> int -> int as opposed to (int * int) -> int? To me, the second makes sense because it "accepts" a 2-tuple (the addends) and returns a single int (their sum).
Thank you!
You can make a language where (+) has the type (int * int) -> int. In fact, SML works exactly this way. It just affects the meaning of infix operators. However OCaml conventions strongly favor the use of curried functions (of the type a -> b -> c) rather than uncurried ones. One nice result is that you can partially apply them. For example ((+) 7) is a meaningful expression of type int -> int. I find this notation useful quite often.
This might seem a little unhelpful, but it's because the function takes two arguments.
When a function takes a tuple, it is in effect taking a single argument.
Because (+) is an inline function, taking a single argument would not be useful, as it would look like + (1,2) as opposed to 1 + 2.