ocaml syntax error in REPL mode - syntax-error

This part of my code always shows me some syntx error: operator expected in the ocaml REPL. The error is on the let of the line "let rec projected ...". What might it be? conditions is defined as a string list and aTable is (string list * string list* (string list) list)
let project (conditions, aTable)=(
let trueFalseList = match aTable with
_,cols,_ -> dataMatcher(cols, conditions)
let rec projected (aTable, trueFalseList) = match aTable with
name,[],[] -> name,[],[]
|name,cols,[] -> newLineMaker ((List.hd cols), trueFalseList)::projected(name,(List.tl cols),[])
|name,cols,vals -> newLineMaker ((List.hd vals), trueFalseList)::projected(name,cols,(List.tl vals))
)

The lines typed into an OCaml REPL in essence form an OCaml module. At the outermost level of a module you can have
let name = value
to define a global named value of the module.
In your case, you have let project (conditions, aTable) = value. In other words, you're defining a function project that takes a pair of values as its parameter.
In any places other than the outermost level of a module, there are no global names. So every let must be followed by in. This is the case in the definition of your project function, and is what the interpreter is complaining about. It is expecting to see in, or a continuation of the expression (i.e., an operator of some sort).
It's not clear what your function project is supposed to return. What is the type of project as a whole?

Related

Partial application of Printf.ksprintf

I'm trying to write a version of Printf.printf that always appends a newline character after writing its formatted output. My first attempt was
# let say fmt = Printf.ksprintf print_endline fmt;;
val say : ('a, unit, string, unit) format4 -> 'a = <fun>
The type signature looks right and say works as expected. I noticed that fmt is listed twice, and thought that partial application could eliminate it. So I tried this instead:
# let say = Printf.ksprintf print_endline;;
val say : ('_weak1, unit, string, unit) format4 -> '_weak1 = <fun>
The function definition looks cleaner, but the type signature looks wrong and say no longer works as expected. For example, say doesn't type check if the format string needs a variable number of arguments: I get an error that say "is applied to too many arguments".
I can use the let say fmt = … implementation, but why doesn't partial application work?
OCaml's type-checker loses polymorphism during partial application. That is, when you partially apply a function, the resulting function is no longer polymorphic. That's why you see '_weak1 in the second type signature.
When you include the fmt argument, you help the type-checker recognize that polymorphism is still present.
This process is called "eta conversion." Removing your fmt argument is "eta reduction" and adding it back in is called "eta expansion." You may encounter that terminology when working with other functional programming languages.
This is the value restriction at work: https://ocaml.org/manual/polymorphism.html#s:weak-polymorphism . In brief, only syntactic values can be safely generalized in let-binding in presence of mutable variables in the language.
In particular,
let f = fun x -> g y x
is a syntactic value that can be generalized, whereas
let f = g y
is a computation that cannot (always) be generalized.
A example works quite well to illustrate the issue, consider:
let fake_pair x =
let store = ref None in
fun y ->
match !store with
| None ->
store := Some y;
x, y
| Some s ->
x, s
then the type of fake_pair is 'a -> 'b -> 'a * 'b.
However, once partially applied
let p = fake_pair 0
we have initialized the store mutable value, and it is important that all subsequent call to p share the same type (because they must match the stored value). Thus the type of p is '_weak1 -> int * '_weak1 where '_weak1 is a weak type variable, aka a temporary placeholder for a concrete type.

In OCaml using Base, how do you construct a set with elements of type `int * int`?

In F#, I'd simply do:
> let x = Set.empty;;
val x : Set<'a> when 'a : comparison
> Set.add (2,3) x;;
val it : Set<int * int> = set [(2, 3)]
I understand that in OCaml, when using Base, I have to supply a module with comparison functions, e.g., if my element type was string
let x = Set.empty (module String);;
val x : (string, String.comparator_witness) Set.t = <abstr>
Set.add x "foo";;
- : (string, String.comparator_witness) Set.t = <abstr>
But I don't know how to construct a module that has comparison functions for the type int * int. How do I construct/obtain such a module?
To create an ordered data structure, like Map, Set, etc, you have to provide a comparator. In Base, a comparator is a first-class module (a module packed into a value) that provides a comparison function and a type index that witnesses this function. Wait, what? Later on that, let us first define a comparator. If you already have a module that has type
module type Comparator_parameter = sig
type t (* the carrier type *)
(* the comparison function *)
val compare : t -> t -> int
(* for introspection and debugging, use `sexp_of_opaque` if not needed *)
val sexp_of_t : t -> Sexp.t
end
then you can just provide to the Base.Comparator.Make functor and build the comparator
module Lexicographical_order = struct
include Pair
include Base.Comparator.Make(Pair)
end
where the Pair module provides the compare function,
module Pair = struct
type t = int * int [##deriving compare, sexp_of]
end
Now, we can use the comparator to create ordered structures, e.g.,
let empty = Set.empty (module Lexicographical_order)
If you do not want to create a separate module for the order (for example because you can't come out with a good name for it), then you can use anonymous modules, like this
let empty' = Set.empty (module struct
include Pair
include Base.Comparator.Make(Pair)
end)
Note, that the Pair module, passed to the Base.Comparator.Make functor has to be bound on the global scope, otherwise, the typechecker will complain. This is all about this witness value. So what this witness is about and what it witnesses.
The semantics of any ordered data structure, like Map or Set, depends on the order function. It is an error to compare two sets which was built with different orders, e.g., if you have two sets built from the same numbers, but one with the ascending order and another with the descending order they will be treated as different sets.
Ideally, such errors should be prevented by the type checker. For that we need to encode the order, used to build the set, in the set's type. And this is what Base is doing, let's look into the empty' type,
val empty' : (int * int, Comparator.Make(Pair).comparator_witness) Set.t
and the empty type
val empty : (Lexicographical_order.t, Lexicographical_order.comparator_witness) Set.t
Surprisingly, the compiler is able to see through the name differences (because modules have structural typing) and understand that Lexicographical_order.comparator_witness and Comparator.Make(Pair).comparator_witness are witnessing the same order, so we can even compare empty and empty',
# Set.equal empty empty';;
- : bool = true
To solidify our knowledge lets build a set of pairs in the reversed order,
module Reversed_lexicographical_order = struct
include Pair
include Base.Comparator.Make(Pair_reveresed_compare)
end
let empty_reveresed =
Set.empty (module Reversed_lexicographical_order)
(* the same, but with the anonyumous comparator *)
let empty_reveresed' = Set.empty (module struct
include Pair
include Base.Comparator.Make(Pair_reveresed_compare)
end)
As before, we can compare different variants of reversed sets,
# Set.equal empty_reversed empty_reveresed';;
- : bool = true
But comparing sets with different orders is prohibited by the type checker,
# Set.equal empty empty_reveresed;;
Characters 16-31:
Set.equal empty empty_reveresed;;
^^^^^^^^^^^^^^^
Error: This expression has type
(Reversed_lexicographical_order.t,
Reversed_lexicographical_order.comparator_witness) Set.t
but an expression was expected of type
(Lexicographical_order.t, Lexicographical_order.comparator_witness) Set.t
Type
Reversed_lexicographical_order.comparator_witness =
Comparator.Make(Pair_reveresed_compare).comparator_witness
is not compatible with type
Lexicographical_order.comparator_witness =
Comparator.Make(Pair).comparator_witness
This is what comparator witnesses are for, they prevent very nasty errors. And yes, it requires a little bit of more typing than in F# but is totally worthwhile as it provides more typing from the type checker that is now able to detect real problems.
A couple of final notes. The word "comparator" is an evolving concept in Janestreet libraries and previously it used to mean a different thing. The interfaces are also changing, like the example that #glennsl provides is a little bit outdated, and uses the Comparable.Make module instead of the new and more versatile Base.Comparator.Make.
Also, sometimes the compiler will not be able to see the equalities between comparators when types are abstracted, in that case, you will need to provide sharing constraints in your mli file. You can take the Bitvec_order library as an example. It showcases, how comparators could be used to define various orders of the same data structure and how sharing constraints could be used. The library documentation also explains various terminology and gives a history of the terminology.
And finally, if you're wondering how to enable the deriving preprocessors, then
for dune, add (preprocess (pps ppx_jane)) stanza to your library/executable spec
for ocamlbuild add -pkg ppx_jane option;
for topelevel (e.g., ocaml or utop) use #require "ppx_jane";; (if require is not available, then do #use "topfind;;", and then repeat).
There are examples in the documentation for Map showing exactly this.
If you use their PPXs you can just do:
module IntPair = struct
module T = struct
type t = int * int [##deriving sexp_of, compare]
end
include T
include Comparable.Make(T)
end
otherwise the full implementation is:
module IntPair = struct
module T = struct
type t = int * int
let compare x y = Tuple2.compare Int.compare Int.compare
let sexp_of_t = Tuple2.sexp_of_t Int.sexp_of_t Int.sexp_of_t
end
include T
include Comparable.Make(T)
end
Then you can create an empty set using this module:
let int_pair_set = Set.empty (module IntPair)

In Elm, how to use comparable type in a tagged unions types?

I can define a tagged unions type like that:
type Msg
= Sort (Product -> Float)
But I cannot define it like:
type Msg
= Sort (Product -> comparable)
The error says:
Type Msg must declare its use of type variable comparable...
But comparable is a pre-defined type variable, right?
How do I fix this?
This question feels a little like an XY Problem. I'd like to offer a different way of thinking about passing sorting functions around in your message (with the caveat that I'm not familiar with your codebase, only the examples you've given in your question).
Adding a type parameter to Msg does seem a bit messy so let's take a step back. Sorting involves comparing two of the same types in a certain way and returning whether the first value is less than, equal to, or greater than the second. Elm already has an Order type using for comparing things which has the type constructors LT, EQ, and GT (for Less Than, EQual, and Greater Than).
Let's refactor your Msg into the following:
type Msg
= Sort (Product -> Product -> Order)
Now we don't have to add a type parameter to Msg. But how, then, do we specify which field of Product to sort by? We can use currying for that. Here's how:
Let's define another function called comparing which takes a function as its first argument and two other arguments of the same type, and return an Order value:
comparing : (a -> comparable) -> a -> a -> Order
comparing f x y =
compare (f x) (f y)
Notice the first argument is a function that looks similar to what your example was trying to attempt in the (Product -> comparable) argument of the Sort constructor. That's no coincidence. Now, by using currying, we can partially apply the comparing function with a record field getter, like .name or .price. To amend your example, the onClick handler could look like this:
onClick (Sort (comparing .name))
If you go this route, there will be more refactoring. Now that you have this comparison function, how do you use it in your update function? Let's assume your Model has a field called products which is of type List Product. In that case, we can just use the List.sortWith function to sort our list. Your update case for the Sort Msg would look something like this:
case msg of
Sort comparer ->
{ model | products = List.sortWith comparer model.products } ! []
A few closing thoughts and other notes:
This business about a comparing function comes straight from Haskell where it fulfills the same need.
Rather than defining the Sort constructor as above, I would probably abstract it out a little more since it is such a common idiom. You could define an alias for a generalized function like this, then redefine Msg as shown here:
type alias Comparer a =
a -> a -> Order
type Msg
= Sort (Comparer Product)
And to take it one step further just to illustrate how this all connects, the following two type annotations for comparing are identical:
-- this is the original example from up above
comparing : (a -> comparable) -> a -> a -> Order
-- this example substitutues the `Comparer a` alias, which may help further
-- your understanding of how it all ties together
comparing : (a -> comparable) -> Comparer a
The error you're getting is saying that comparable is an unbound variable type. You need to either fully specify it on the right hand side (e.g. Product -> Int) or specify you would like it to be polymorphic on the left hand side. Something like this:
type Msg a = Sort (Product -> a)
The question you ask about comparable is answered here: What does comparable mean in Elm?

Ocaml unbound module

I'm learning Ocaml language but i have a problem with my modules when i want to compile them.
So, I have a module with the name Door and an other one with the name Case. Into each one, i have a type paramater with the other module :
Door.mli
type t = bool -> Case.u -> t
Case.mli
type u = bool -> Door.t -> u
When i want to compile, i have this error :
File "door.mli", line 14, characters 23-29:
Error: Unbound module Case
Have you got an idea ?
Thanks you
You have two mutually recursive modules, which is always tricky. One way to get them to work is to define them in the same file using module rec A ... and B ....
However, you also have the problem that your types are cyclic. The definition:
type t = bool -> Case.u -> t
is not normally accepted by OCaml either. You can get it to be accepted by specifying -rectypes on the compiler or interpreter command line.
I fear that you'll find these structures to be difficult to work with. The reason they're difficult to define is that they're not usually what you want. You might try starting with more straightforward types if possible.
My advice: get those two types out of door.ml and case.ml, and make Door and Case depend on a common Types module with:
type door = Door of bool -> case -> door
and case = Case of bool -> door -> case

Understanding functors in OCaml

I'm quite stuck with the following functor problem in OCaml. I paste some of the code just to let you understand. Basically
I defined these two modules in pctl.ml:
module type ProbPA = sig
include Hashtbl.HashedType
val next: t -> (t * float) list
val print: t -> float -> unit
end
module type M = sig
type s
val set_error: float -> unit
val check: s -> formula -> bool
val check_path: s -> path_formula -> float
val check_suite: s -> suite -> unit
end
and the following functor:
module Make(P: ProbPA): (M with type s = P.t) = struct
type s = P.t
(* implementation *)
end
Then to actually use these modules I defined a new module directly in a file called prism.ml:
type state = value array
type t = state
type value =
| VBOOL of bool
| VINT of int
| VFLOAT of float
| VUNSET
(* all the functions required *)
From a third source (formulas.ml) I used the functor with Prism module:
module PrismPctl = Pctl.Make(Prism)
open PrismPctl
And finally from main.ml
open Formulas.PrismPctl
(* code to prepare the object *)
PrismPctl.check_suite s.sys_state suite (* error here *)
and compiles gives the following error
Error: This expression has type Prism.state = Prism.value array
but an expression was expected of type Formulas.PrismPctl.s
From what I can understand there a sort of bad aliasing of the names, they are the same (since value array is the type defined as t and it's used M with type s = P.t in the functor) but the type checker doesn't consider them the same.
I really don't understand where is the problem, can anyone help me?
Thanks in advance
(You post non-compilable code. That's a bad idea because it may make it harder for people to help you, and because reducing your problem down to a simple example is sometimes enough to solve it. But I think I see your difficulty anyway.)
Inside formulas.ml, Ocaml can see that PrismPctl.s = Pctl.Make(Prism).t = Prism.t; the first equality is from the definition of PrismPctl, and the second equality is from the signature of Pctl.Make (specifically the with type s = P.t bit).
If you don't write an mli file for Formulas, your code should compile. So the problem must be that the .mli file you wrote doesn't mention the right equality. You don't show your .mli files (you should, they're part of the problem), but presumably you wrote
module PrismPctl : Pctl.M
That's not enough: when the compiler compiles main.ml, it won't know anything about PrismPctl that's not specified in formulas.mli. You need to specify either
module PrismPctl : Pctl.M with type s = Prism.t
or, assuming you included with type s = P.t in the signature of Make in pctl.mli
module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s
This is a problem I ran into as well when learning more about these. When you create the functor you expose the signature of the functor, in this case M. It contains an abstract type s, parameterized by the functor, and anything more specific is not exposed to the outside. Thus, accessing any record element of s (as in sys_state) will result in a type error, as you've encountered.
The rest looks alright. It is definitely hard to get into using functors properly, but remember that you can only manipulate instances of the type parameterized by the functor through the interface/signature being exposed by the functor.