How to reference an argument that is a functor - ocaml

I'm defining a module using the below header:
module MakePuzzleSolver
(MakeCollection
: functor (Element : sig type t end) ->
(Collections.COLLECTION with type elt = Element.t))
(Puzzle : PUZZLEDESCRIPTION)
: (PUZZLESOLVER with type state = Puzzle.state
and type move = Puzzle.move) =
This is the first time I've ever tried using a functor as an argument, and I'm a little confused about how/whether I can include references within the MakePuzzleSolver module to functions that are included in the functor's signature. E.g., the functor's signature includes a function called "add" that I'd like to reference, but of course when I try MakeCollection.add I get a "functor cannot have components" error message. Do I need to create an implementation of the functor within MakePuzzleSolver to be able to reference it?

You need to apply the functor. Much like with a function (and this is what it is underneath the hood), you need to apply a function to its argument in order to use its result.
In your example, it looks like that you're missing the final piece of the puzzle - you need an extra argument that will denote the element of your collection, e.g.,
module MakePuzzleSolver
(MakeCollection
: functor (Element : sig type t end) ->
(Collections.COLLECTION with type elt = Element.t))
(Puzzle : PUZZLEDESCRIPTION)
(Element : sig type t end) (* the missing element *)
: (PUZZLESOLVER with type state = Puzzle.state
and type move = Puzzle.move) = struct
module Collection = MakeCollection(Element)
(* now you can use Collection.add *)
...
end

A functor that creates a new kind of collection is not a collection in itself.
You cannot reference the add function of a module that does not exist yet.
It might help to precise in which context you are trying to reference this add function.

Related

Meaning of code involving function binding

Can someone explain what is going on in the below code snippet line by line
auto enq_func = [](std::queue<reg_t>* q, uint64_t x) { q->push(x); };
std::queue<reg_t> fromhost_queue;
std::function<void(reg_t)> fromhost_callback =
std::bind(enq_func, &fromhost_queue, std::placeholders::_1);
I think I get the gist of it, that fromhost_queue is a std::queue of each element of type reg_t which was typedef in the beginning of the code as uint64_t and its enqueue functionality is defined using the above three lines something like that.
I have trouble understanding line 1 as I haven't come across this type of function declaration like =[](...){...}; is this some sort of shorthand or something
Also, in the bind() part in line 3, the first argument is a function(here named as enq_func) that bind will be applied on the second argument mostly used to pass a reference of a queue the enq_func will be applied but the last is an argument which will we enqueued but I don't see the enq_func having any arguement
can someone clarify this?
This is a slightly overly-complex way to create a function-like callable object that pushes its argument into fromhost_queue. That is, fromhost_callback(123) will end up calling fromhost_queue.push(123).
auto enq_func = [](std::queue<reg_t>* q, uint64_t x) { q->push(x); };
This is a lambda expression that creates a callable object that pushes its second parameter into the queue pointed to by the first parameter. That is, enq_func(&fromhost_queue, 123) will call fromhost_queue.push(123).
std::function<void(reg_t)> fromhost_callback =
std::bind(enq_func, &fromhost_queue, std::placeholders::_1);
This creates a new callable object that wraps enq_func and automatically supplies its first argument, then stores that in a type-erased std::function container. So fromhost_callback(123) will automatically call enq_func(&fromhost_queue, 123).
There's no reason to do this in two steps though, a single lambda will do fine.
Assuming there's a good reason to use std::function then this will do the same thing:
std::queue<reg_t> fromhost_queue;
std::function<void(reg_t)> fromhost_callback =
[&fromhost_queue](uint64_t x) { fromhost_queue.push(x); }

Please explain this Map key-type constraint recipe to me

I am new to OCaml and such languages.
I have been experimenting with Map and ended up with:
type thing = ThingA | ThingB
module ThingMap = Map.Make(String)
let things = [
("a", ThingA);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
So far so good, I've got a map of strings to things.
Then I was reading that Map.Make(String) only enforces the type of the keys, the values could be any type.
I found this recipe for enforcing that values should be of thing type:
let m: thing ThingMap.t ref = ref ThingMap.empty
The recipe seems useful but I don't understand how it works.
Three questions:
what does m represent? it has type type thing ThingMap.t ref but that doesn't mean much to me... is it useful for anything? can I just rename it to _?
does declaring this in a module enforce the constraint for all instances of ThingMap in any module? (is "instances" the right word?)
what's up with the ref and empty? how does this work?
Update
After experimenting a bit more with benefit of #Jeffrey Scofield's helpful answer I can see that this recipe is not needed in my case (initialising an immutable Map from a list of key-value pairs).
First I observe that I get a type error if subsequent elements of the list do not have same type as the first element:
let things = [
("a", ThingA);
("b", 123)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
Cool, but that's not enough because if the "wrong" element is in the first position I get the "wrong" type error for the constraint I intended:
let things = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type thing but an expression was expected of type
int
I can fix this by understanding that the part after the colon in let m: thing ThingMap.t ... is a type signature, so I can get the result I want by adding a signature to things:
let things: thing ThingMap.t = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
Here the first item has wrong type, but I get the type error I wanted.
m is a global variable (a name) that is declared by the let. This is not a sweeping declaration that all values of type ThingMap contain values of type thing. It's just a declaration of one such map (accessed through a reference). You could later use ThingMap.t with values of any type.
# let m : thing ThingMap.t ref = ref ThingMap.empty;;
val m : thing ThingMap.t ref = {contents = <abstr>}
# let n : int ThingMap.t ref = ref ThingMap.empty;;
val n : int ThingMap.t ref = {contents = <abstr>}
Here I declared a value m, a reference to a map from strings to things. Then I declared a value n, a reference to a map from strings to ints.
The left side of let is a pattern. You can certainly use _ for this pattern but then you would have no name by which to refer to your map.
This declaration doesn't enforce any constraints on anything except the specific variable m.
If you don't know what references are, you should learn about them. In essence a reference is a mutable cell that always contains a value of one type, but it can be modified to contain different values of the type. (On the other hand, it's good when starting with OCaml to try to code without using references.)
ThingMap.empty is a map with no keys (and hence no values).
If you really want to control the values used in ThingMap, you can define it in a module that specifies types for the functions that access the map. Once you've defined ThingMap.t as a visible type, there's no way to change its meaning to make it more restricted.
If you just want a handy name for the type of maps from strings to things, you can give it a name:
type thingmap = thing ThingMap.t
Update
Here is a previous SO discussion of OCaml (immutable) variable bindings and references:
What is the difference between let-bindings and references in OCaml?

Why my cast on user def type doesnt work?

type card = int
type game = { dimension : int; p1 : card list; }
let fn (_dimension : int) (p1 : card list) : bool =
(int)p1 = (int)_dimension * 2
I want to check that p1 is exactly twice the size of dimension.
Your code doesn't look very much like OCaml code, so it's difficult to know how to help :-)
There is no operation in OCaml to change the type of a value. That wouldn't make sense in a strongly typed language. There are some things you can do with types, but "casting" isn't one of them.
So, there is no valid expression that looks like (int) expr. As #glennsl points out, there is a function that returns the length of a list. If that's what you're trying to calculate, you can use List.length _dimension. The other occurrences of (int) you can just remove. They aren't valid OCaml.
Your definition of fn doesn't use the type game anywhere, so the definition of game is unnecessary. However it makes me worry that you're expecting the definition to have an effect.
If you leave out all the type ascriptions in your definition of fn the compiler will deduce the most general type for your function. This means you can call it with any list to check its length. That would be more idiomatic in OCaml. I.e., you don't need to specify that p1 is a list of cards. The function makes sense for any list.

SML constantly implementation

I read about function constantly:
fun constantly k a = k
But I don't understand how to work with it.
I tried that way:
val a = constantly 10;
stdIn:32.5-32.28 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val a = fn : ?.X1 -> int * int -> int
It works that way:
val a = constantly 10 ();
val a : int = 10
But not that way:
val a = constantly 10;
a ();
stdIn:36.1-36.5 Error: operator and operand don't agree [tycon mismatch]
operator domain: ?.X1
operand: unit
in expression:
a ()
Can anybody help me with understanding in that function?
This is the value restriction. Understanding it is important to understand partial application in ML. It is necessary due to mutability in the presence of polymorphism.
http://mlton.org/ValueRestriction
http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html
Any time you see such a warning, you can fix it by eta-expanding the expression.
fun a x = constantly 10 x;
The thing is that fun constantly k a = k has type 'a -> 'b -> 'a
A partial function invocation like constantly 10 would be considered an expanding expression, and SML would be expecting to be capable to infer the actual types of the type variables for constantly at this point. That is, SML would be expecting that it could replace the type variables 'a and 'b with some concrete type T at this point.
Since your parameter a is not used in the body of your constantly function, SML cannot infer anything about it.
You would expect an expression like val a = constantly 10 to produce a type like 'b -> int, but instead, since SML finds that it cannot determine the type of 'b then it changes it for a dummy (concrete) type ?.X1, and that's why you end up with a function type ?.X1 -> int.
This is just SML telling you that it could not properly infer 'b because you did not provide enough type information for it in your expanding expression and so it has assigned a dummy concrete type to it, which basically renders your function impossible to use.
So, an alternative solution to the one already mentioned in another post would be to qualify your resulting function with a concrete type.
For instance, this should work:
val a = constantly 10: (int -> int)
With the obvious disadvantage of having qualified your type variable 'b as int, therefore, the curried function a is no longer a polymorphic function, but it is indeed a curried function. For this to work we would need to know the concrete type of 'b at the point where we are creating the curried function.
But if you still need the curried function to be polymorphic, because you cannot assume a specific/concrete type for 'b at that point then, as the other answer mentions, you will need to provide yet another argument that carries your polymorphic type:
val a = fn x => constantly 10 x
Which is basically the same thing in seanmcl's answer.
This would work because now x would carry the concrete type for 'b in your invocation to constantly 10 x within the wrapper function. Such concrete type will be defined when you invoke the curried function a (i.e. val _ = a(15) in this case 'b is int)

Polymorphic function as return value and value restriction in SML

Basically, I want to have a function to return a polymorphic function, some thing like this:
fun foo () = fn x => x
So the foo function takes in a value of type unit and returns a polymorphic identity function
and the compiler is happy with that, it gives me:
val foo = fn : unit -> 'a -> 'a
but once I actually call the foo function, the return value is not what I expected
val it = fn : ?.X1 -> ?.X2
Can't generalize because of value restriction it says, any help? thanks in advance
For technical reasons, you are not allowed to generalize (i.e., make polymorphic) the results of a function call. The result of a call must have a monomorphic type. If this weren't the case, you could subvert the type system by the following dirty trick:
Call ref [] and get back a list of type forall 'a . 'a list ref
Insert a string.
Remove a function
and there you are: you are now executing the contents of an arbitrary string as code. Not Good.
By insisting that the value returned by ref [] be monomorphic, you ensure that it can be used as a list of strings or a list of functions but not both. So this is part of the price we pay for type safety.