When I try to compile my code, I get the following error
Error: Signature mismatch:
...
Values do not match:
val filter_map : ('b -> 'b option) -> 'b t -> 'b list
is not included in
val filter_map : ('b -> 'a option) -> 'b t -> 'a list
File "set.ml", line 7, characters 2-55: Expected declaration
File "treeSet.ml", line 105, characters 10-20: Actual declaration
However, my signature is actually declared as follows.
module type SetS = sig
type 'a t
val empty : 'a t
val insert : 'a t -> 'a -> 'a t
val contains : 'a t -> 'a -> bool
val filter_map : ('a -> 'b option) -> 'a t -> 'b list
end
For some reason, the error I get when compiling shows a different type declaration than the one I have actually implemented. Why is this happening and how can I fix this?
The error Signature mismatch means that the derived signature of a module differs from the specified signatures. E.g., suppose we want to write a module with the following signature,
module type Expected = sig
val filter : ('a -> bool) -> 'a list -> 'a list
end
and we write,
module Real : Expected = struct
let filter = List.filter_map
end
The error message that we get will be,
Signature mismatch:
Modules do not match:
sig val filter : 'a list -> f:('a -> 'b option) -> 'b list end
is not included in
Expected
Values do not match:
val filter : 'a list -> f:('a -> 'b option) -> 'b list
is not included in
val filter : ('a -> bool) -> 'a list -> 'a list
So the problem is that our proposed implementation of filter has type 'a list -> f:('a -> 'b option) -> 'b list but what we really wanted and expected for the type of filter is ('a -> bool) -> 'a list -> 'a list. That is what the error message says.
Applying to your case, your implementation has the inferred type ('b -> 'b option) -> 'b t -> 'b list which doesn't match with the required type ('b -> 'a option) -> 'b t -> 'a list. Notice that your type is less general. It filters list without changing the type of the element. So it can only filter map int list to int list, string list to string list and so on, unlike the more generic implementation that is able to map int list to string list.
To rectify the problem, you need to carefully review your implementation. Make sure that you don't have branching instructions (like if/then/else, match) such that one branch returns an element or elements of the input list and the other branch returns the element or elements of the output list. To demonstrate this, consider the following implementation,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> xs
| Some x -> x :: filter_map f xs
Here I made an error, by returning xs, the input list, when f x evaluates to None. The other branch, constructs the output list, so we got the types of input and output lists unified. In the correct implementation, you should recursively call filter_map in both branches,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> filter_map f xs
| Some x -> x :: filter_map f xs
Related
Based on this definition:
An append list is a (simple) implementation of the list abstract data type that makes construction cheap (O(1)), but makes destruction expensive (O(n)). The 'a alistNN and 'a alist types are defined as follows:
datatype 'a alistNN = Sing of 'a | Append of 'a alistNN * 'a alistNN
datatype 'a alist = Nil | NonNil of 'a alistNN
The 'a alistNN type represents the “non-nil” append lists, while the 'a alist type represents arbitrary (nil or non-nil) append lists.
Im asked to make a map function defined as:
fun alistMap (f: 'a -> 'b) (xs: 'a alist): 'b alist =
That performs a map on an append list.
I have it defined as follows:
fun alistMap (f: 'a -> 'b) (xs: 'a alist): 'b alist =
case xs of
Nil => Nil
| NonNil xs =>
let
fun mapNN(f: 'a -> 'b) (xs: 'a alist): 'b alist =
case xs of
Sing x => Sing (f x)
| Append (ys, zs) =>
let
val ws = mapNN f ys
val ts = mapNN f zs
in
alistAppend (ys , zs)
end
in
mapNN f xs
end
I keep getting clashing types, especially with:
Sing x => Sing (f x)
Any idea what might be causing this?
Your inner function mapNN is annotated with the wrong type. The constructors Sing and Append form values of type alistNN, not alist. So it should instead be annotated as follows.
fun mapNN (f : 'a -> 'b) (xs : 'a alistNN) : 'b alistNN = ...
There are a couple other issues with your code:
The line alistAppend (ys, zs) has type 'a alist but the function needs to return something of type 'b alistNN, so this will be a type error. As a hint to fix this problem, notice that you create values ws and ts but then never use them... ;)
Once you fix mapNN, you will have a type error on the line mapNN f xs, because it has type 'b alistNN, but needs to be something of type 'b alist.
In summary, be careful about the difference between alist and alistNN. These are two different types, with different constructors, and fundamentally different meanings!
I have to write a function to remove elements from a lazy list. Indexes of elements to be removed are in list xs.
I don't know where I should sort xs? When I try in this way I get "Error: This expression has type...".
type 'a llist = LNil | LCons of 'a * (unit -> 'a llist)
let rec remove xs ll =
let rec helper =
function
| (_, i, LNil) -> LNil
| (h::t, i, LCons(x, xf)) -> if h = i then helper (t, (i + 1), xf())
else LCons(x, fun() -> helper (h::t, (i + 1), xf()))
| ([], i, LCons(x, xf)) -> LCons(x, xf)
in helper (List.sort xs, 0, ll);;
List.sort from OCaml standard library has the following interface:
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
That means, that it accepts a function and a list. The function should have type 'a -> 'a -> int, i.e., it takes two elements of arbitrary type 'a and returns a value of type int that defines the mutual order of the arguments. The second argument is a list of values, where each value has type 'a. A usual invocation of the sort function is:
List.sort compare [2;1;4;3]
So with this knowledge we can tackle with your program:
You invoke List.sort on xs this has two consequences:
type inference system concludes that xs is a function of type 'a -> 'a -> int.
The result of List.sort xs is a function of type 'a list -> 'a list. This is because, List.sort requires two arguments, but you provided only one.
(List.sort xs) is a function that takes a list & returns a list - as xs is supposed to be the function that sorts the element of the list; you miss to pass a list as arg.
...whereas a list is expected.
I was trying (just out of interest) to do this:
module type CAT = sig
type ('a, 'b) t
val id : ('a, 'a) t
val (#) : ('b, 'c) t -> ('a, 'b) t -> ('a, 'c) t
end
module Lst = struct
type ('a, 'b) t = 'a list constraint 'a = 'b
let id = []
let (#) = (#)
end
module L : CAT = Lst (* (error) *)
But I get:
Type declarations do not match:
type ('b, 'a) t = 'b list constraint 'a = 'b
is not included in
type ('a, 'b) t
Why isn't this safe? Everything that can see the concrete type can also see the constraint, so I don't think you could make something with a wrong type (e.g. call # with a (string, int) t argument).
Update: to those saying that my module doesn't implement the signature because it requires the types to be the same, consider that the following (which just wraps the lists in a List variant) is accepted despite having the same behaviour:
module Lst = struct
type ('a, 'b) t =
List : 'a list -> ('a, 'a) t
let id = List []
let (#) (type a) (type b) (type c) (a:(b, c) t) (b:(a, b) t) : (a, c) t =
match a, b with
| List a, List b -> List (a # b)
end
The example can be reduced to the type definition alone:
module type S =
sig
type ('a, 'b) t
end
module M =
struct
type ('a, 'b) t = 'a list constraint 'a = 'b
end
As Jeffrey already pointed out, M is not of type S, because it allows fewer applications of t: according to signature S, the type (int, string) t would be perfectly legal (it is well-formed), but M does not allow this type ((int, string) M.t is not a legal type, because it violates the explicit constraint).
All that is completely independent from the question whether the type is actually inhabited, i.e., whether you can construct values of the type. In your second example, the module makes the respective type well-formed, though it is uninhabited. Uninhabited types are legal, however, and sometimes even useful (see e.g. the concept of phantom types).
The type signature CAT is more general than the type of the Lst module. You need to put the type constraint on the abstract type too, i.e. type ('a, 'b) t constraint 'a = 'b.
This gives us the following:
module type CAT = sig
type ('a, 'b) t constraint 'a = 'b
val id : ('a, 'a) t
val (#) : ('b, 'c) t -> ('a, 'b) t -> ('a, 'c) t
end
which is printed as follows by the toplevel, showing a single type variable in the signature of (#):
module type CAT =
sig
type ('b, 'a) t constraint 'a = 'b
val id : ('a, 'a) t
val ( # ) : ('c, 'c) t -> ('c, 'c) t -> ('c, 'c) t
end
Error messages of the form "type x is not included in type y" refer to types or module types as specifications of sets of possible values, hence the use of the term "included".
In the case of a module implementation (Lst), we have a module type for it. Applying a signature (module type CAT) to a module is only allowed if that signature is as specialized (equal set) or more specialized (strict subset) than the original signature of the module.
One can write module X : sig val f : unit -> unit end = struct let f x = x end
but not module X : sig val f : 'a -> 'a end = struct let f () = () end. The latter gives the following error:
Error: Signature mismatch:
Modules do not match:
sig val f : unit -> unit end
is not included in
sig val f : 'a -> 'a end
Values do not match:
val f : unit -> unit
is not included in
val f : 'a -> 'a
This is different than placing type constraints on certain expressions, in which case the constraint is a mask to be applied (a set to intersect with) rather than a subset. For example it is fine to write let f : unit -> 'a = fun x -> x even though f's signature ends up being unit -> unit, a strict subset - or subtype - of unit -> 'a.
Your Lst module doesn't seem to me to have the type CAT. CAT allows the two types 'a and 'b to be independent. The Lst module requires them to be the same. If the L module were of type CAT then it should allow me to make something of type (string, int) t but it doesn't.
The error message is a little confusing, at least to me.
I wanted to write a function with following signature to use in association dictionary
empty: unit -> ('a * 'b) list
I am assuming it will be something like
let empty () = ...
But how can I create a list with specific type?
If your function returns an empty list it will have the type you want:
# let empty () : ('a * 'b) list = [];;
val empty : unit -> ('a * 'b) list = <fun>
The natural type of this function is unit -> 'a list, but OCaml will let you "slim down" the type into a more specific one.
You can specify a type for any expression in the form ( expr : type ):
# let empty () = ([] : ('a * 'b) list);;
val empty : unit -> ('a * 'b) list = <fun>
Of course, the type has to be correct (must unify with the inferred type of the expression).
Update
As newacct points out, you could use a value rather than a function.
# let (empty : ('a * 'b) list) = [];;
val empty : ('a * 'b) list = []
This is a common way to define an empty pure structure (as in the Map module).
Write any Ocaml function whose type is ('a -> 'b) list -> 'a -> 'b list
('a -> 'b) list is the part that confuses me the most. I'm new to OCaml and having a hard time understanding how to write a function to get a specific datatype type.
# let int x = x+1;;
# let fcn = [int; int];;
So I'm passing a function a function and a variable. I'm going to take that variable an add it to each element of the list and return the list?
('a -> 'b) means a function which goes from type 'a to type 'b. Basically you need to make a function which takes a list of functions that take 'a and return 'b, plus a specific 'a value, and which returns a list of 'b values (probably by applying each function of the list of functions to the specific 'a value).
As this is homework, I will not provide you with a complete solution. But, as a hint, I would suggest that you take a look at this implementation of the familiar map function:
let rec map f = function
| [] -> []
| x :: xs -> f x :: map f xs
It has type ('a -> 'b) -> 'a list -> 'b list which means that it takes as its first argument a function that takes values of some type 'a to values of some type 'b, as its second argument a list of elements of type 'a, and that it produces a list of elements of type 'b. It proceeds by pattern matching on the argument list and, recursively applying the function (f) to every element x of the list.
Now have a look at the type of the function that you have to write? What does it tell you about the required behaviour of that function? Keeping the implementation of the map function in mind, how would you write your function?
('a -> 'b) list -> 'a -> 'b list
This means that your function has two parameters
A list of ('a -> 'b) which represents a function taking an element of type 'a as a parameter and returning an element of type 'b. As you can see, these types are abstract, so they could be of any types for instance (int -> int) or (int -> float) etc...
An elements of types 'a. Notice that this type must be the same as the parameter of your function.
So you'll build the resulting list with the element you give as a parameter.
Here is a little example:
let action l a =
let rec todo l res =
match l with
| [] -> res
| h :: t -> todo t res#[h a] in
todo l []
so here, any function of type int -> int will be accepted. The same thing goes for any other type as long as you don't mix them with other types.
let rec func f a = match f with (* ( 'a->'b ) list -> 'a -> 'b list *)
|[]->[]
|x::lr -> x a :: func lr a;;
that may help ! it works fine
1 - So as we know , ocaml create the type of our function line by line
2 - in this function we have two arguments f and a
3 - ( 'a->'b ) list : for f
4 - 'a : for a ! how ocaml did that ? listen !
5 - when we matched f with [ ] 'blank list' ocaml release that is a list (****)list but doesn't know what contains yet in the last line of the code he will do ok ? nice !
- here we are in the last line of the code and we have only f of type list -
6 - x :: lr means we sort the first element of the element that is matched before : f and we add a here ocaml gives a type for a and for the list elements which is matched : f as first elements ocaml gives them types from 'a to 'z so here we have ('a->'b) list for f and 'a for a
-here we have f of type : ('a->'b) list , and a of type : 'a
7 - the result of this function 'b list so it's up to you to answer in comment ! :D thank you