I'm having a problem where I have one module trying to use another one, but I'm getting an error claiming there's a signature mismatch and I'm not certain why. I was pretty sure I was doing this right though. Here's some code:
module type ITEM =
sig
type item
val leq : item * item -> bool
val initial : item
end
module type HEAP =
sig
type item
type tree
exception InitHeap
val depth : tree -> int
val initHeap : int -> tree
val insert : item * tree -> tree
val isHeap : tree -> bool
val maxHeap : tree -> item
val replace : item * tree -> item * tree
val size : tree -> int
val top : tree -> item
end
module Heap (Item: ITEM) : HEAP =
struct
type item = Item.item
let leq(p, q) : bool = Item.leq(p,q)
let max(p,q) = if leq(p,q) then q else p
and min(p,q) = if leq(p,q) then p else q
let intmax((p : int),q) = if p <= q then q else p
type tree =
| L of item
| N of item * tree * tree
exception InitHeap
let rec initHeap n =
if (n < 1) then raise InitHeap
else if n = 1 then L Item.initial
else let t = initHeap(n - 1)
in N (Item.initial, t, t)
let rec top t =
match t with
| (L i) -> i
| N (i,_,_) -> i
let rec isHeap t =
match t with
| (L _) -> true
| (N(i,l,r)) ->
leq(i,top l) && leq(i,top r) && isHeap l && isHeap r
let rec depth t =
match t with
| (L _) -> 1
| N(i,l,r) -> 1 + intmax(depth l,depth r)
let rec replace (i,h) = (top h, insert(i,h))
and insert (i, h) =
match h with
| L _ -> L i
| N (_,l,r) ->
if leq(i,min(top l,top r))
then N(i,l,r)
else if leq((top l),(top r))
then N(top l,insert(i,l),r)
else N(top r,l,insert(i,r))
let rec size h =
match h with
| L _ -> 1
| N (_,l,r) -> 1 + size l + size r
let rec maxHeap h =
match h with
| (L i) -> i
| N (_,l,r) -> max(maxHeap l, maxHeap r)
end
So Heap includes a bunch of functions that just do simple operations on a Heap but for some reason ocaml thinks that the signature for HEAP is supposed to include functions for ITEM, but I just want to pull ITEM functions into HEAP
The error I get:
Error: Signature mismatch:
Modules do not match:
sig val leq : int * int -> bool end
is not included in
ITEM
The value `initial' is required but not provided
File "lab13.ml", line 28, characters 8-26: Expected declaration
The type `item' is required but not provided
File "lab13.ml", line 26, characters 8-17: Expected declaration
Thanks for any help in advance!
You most probably wrote
module type HEAD = functor (Head:ITEM) -> sig … end
(and not module type HEAD = functor (Head:HEAD) -> sig … end which is recursely using the HEAD module type which is a type error )
when you meant
module type HEAD = sig … end
Adding the functor(HEAD:ITEM) -> … part makes HEAD the signature or a functor. Therefore
module Heap (Item: ITEM) : HEAP
is the same thing as
module Heap (Item: ITEM) : functor(Heap:HEAP) -> sig … end
in other words, the signature that you added make Heap a higher-order functor; which is obviously not the case of the implementation.
Unfortunately, error messages in presence of functors are lacking right now, and the type-checker does not detail error in this specific case for now.
Rewriting the HEAD module type as
module type HEAD = sig … end
should fix this problem.
Related
Im new to f# and i'm trying to make this exercise:
"Implement a function"
let rec nth(n : int) (l : List<'a>) : Option<'a> =
that returns the element in position n in l. The function must handle appropriately the case where the index is invalid
this is my current code but I'm kinda stuck:
let rec nth (n : int) (l : List<'a>) : Option<'a> =
if n > l.Length then
None
else
match l with
| [] -> None
Thanks for the help!
There is a built-in function List.tryItem
let rec nth(n : int) (l : List<'a>) : Option<'a> =
l |> List.tryItem n
Can you use any functionality provided by the core library at all? If so, I suggest the following function:
let nth (n : int) (l : 'a list) : 'a option =
if n < 1 || n > l.Length then None else Some l.[n - 1]
This just checks whether the index is within permitted boundaries, then returns the element at the appropriate index. The index-item operator is zero-based, therefore we need to subtract one from the number passed into the function, and the list iteration is done by the compiler behind the scenes.
If you need to do it completely manually, I suggest the following function:
let nth (n : int) (l : 'a list) : 'a option =
let rec inner i = function
| [] -> None
| x :: _ when i = 0 -> Some x
| _ :: xs -> inner (i - 1) xs
if n < 1 then None else inner (n - 1) l
This checks the lower boundary, and if it is all right, starts to iterate the list using an inner function, and decrementing the index until it is zero so it knows it reached the right index. If the list is shorter, None is returned.
type 'a tree =
| Leaf of 'a
| Node of 'a * 'a tree * 'a tree
let rec foldtree init op = function
| Leaf c -> op c init init
| Node (c, l, r) -> op c (foldtree init op l) (foldtree init op r)
let size' = foldtree 0 (fun _ l r -> 1 + l + r) (* this compiles fine *)
let size'' = foldtree 0 (fun _ l r -> 1 + l + r) (* this doesn't *)
In the above OCaml code, the definitions of size' and size'' are identical yet the latter causes a compilation error:
Error: The type of this expression, '_weak1 tree -> int,
contains type variables that cannot be generalized
They should both fail to compile, as both contain weak type variables. The compiler will only report one fatal error at a time, however.
Incidentally, you would usually fix this problem by eta-expansion:
let size tree = foldtree 0 (fun _ l r -> 1 + l + r) tree
I have this simple function which drives me crazy:
it should be a function of this type :
myfunction : (int * int list) list -> int -> int
For each tuples of the first argument :
When the second argument matches the first element of the tuple then the function return the last element of the list in the tuple.
If no matches it should return -1.
let rec myfunction alist anum =
let last_e l =
let len = List.length l in
List.nth l (len - 1) in
match alist with
| [] -> -1
| (n , ln) :: q -> if n = anum then last_e ln
else myfunction q anum
But my function does not work and I have this error message in utop:
Error: This expression has type 'a option but an expression was expected of type int
I don't know where the "option" type comes from.
This can happen if you are using some OCaml toplevel (e.g. utop) and you have these lines in your .ocamlinit file
#require "core.top" ;;
open Core.Std ;;
This enables the Core libraries, where List.nth has type:
μ> List.nth;;
- : 'a list -> int -> 'a option = <fun>
instead of standard OCaml's List.nth : 'a list -> int -> 'a.
So, when you fire up your toplevel and say:
μ> #use "myfunction.ml";;
you get the same error you cited in the question.
By the way, if you'd like to keep using Core, there is a List.last function.
Given
type 'a set = { insert : 'a -> 'a set; contains : 'a -> bool }
How can I implement
val empty : 'a set
?
I've tried closing over something, say a list, but the return type is wrong.. since it is. (ignoring the fact that the performance characteristics here are terrible :-) )
let empty =
let rec insert_f set a =
match set with
| [] -> a :: []
| k :: rest ->
if k = a then
k :: rest
else
k :: insert_f rest a
in
let rec contains_f set a =
match set with
| [] -> false
| k :: rest ->
if k = key then
true
else contains_f rest a
in
{ insert = insert_f []; contains = contains_f []}
directly writing the empty is not the easiest in such data structure, as you will need to write the insert, which will contains again an insert and so one... So let's write first the insert:
let rec insert : 'a set -> 'a -> 'a set = fun s x -> {
insert = (fun y -> failwith "TODO");
contains = (fun y -> if x = y then true else s.contains y) }
in insert, you want to recursively call insert, but the first parameter will be the record you are writing. So here is the complete solution:
let rec insert : 'a set -> 'a -> 'a set = fun s x ->
let rec ss = {
insert = ( fun y -> insert ss y);
contains = (fun y -> if x = y then true else s.contains y)}
in ss
let rec empty = {
insert = (fun x -> insert empty x);
contains = (fun x -> false)}
First of all, it's bool, not boolean. :)
Second, this definition is quite cumbersome. But you can do something like:
let empty = {
insert=(fun x -> {
insert=(fun x -> assert false);
contains=(fun x-> assert false)});
contains=(fun x -> false)}
with your implementations of insert and contains for non-empty sets in place of "assert false" of course.
A hint for implementing insert and contains: don't use any lists, use compositions of a functions from existing and new sets.
You can find nice examples in e.g. "On Understanding Data Abstraction, Revisited" by W. Cook, that paper is available online.
let rec add_tail l e = match l with
| [] -> [e]
| (h::t) -> h::(add_tail t e)
let rec fill_help l x n = match n = 0 with
true -> l
| false -> add_tail(l, x); fill_help(l, x, n-1)
let fill x n =
let l = [] in
fill_help(l, x, n)
and I'm getting the error in the interpreter
# #use "prac.ml";;
val prod : int list -> int = <fun>
val add_tail : 'a list -> 'a -> 'a list = <fun>
File "prac.ml", line 13, characters 21-27:
Error: This expression has type 'a * 'b
but an expression was expected of type 'c list
line 13 would be
| false -> add_tail(l, x); fill_help(l, x, n-1)
First of all you call fill_help with a tuple as an argument ((l, x, n-1)) even though it's not defined to take one. You should call fill_help as fill_help l x (n-1) instead. Same for add_tail.
Secondly you call a side-effect-free function (add_tail) and throw away its return value. This is almost always an error. It looks like you expect l to be different after the call to add_tail. It won't be. You probably want fill_help (add_tail l x) x (n-1).