How would I proceed with proving these two functions are well typed? I am a bit lost with this question.
let rec reduce f lst u =
match lst with
| [] -> u
| (h::t) -> f h (reduce f t u)
let rec forall2 p l1 l2 =
match (l1,l2) with
| ([],[]) -> true
| ([],_) -> false
| (_,[]) -> false
| ((h1::t1),(h2::t2)) ->
(p h1 h2) && (forall2 p t1 t2)
I won't give a fully-fledged solution since the question looks like an assignment.
To do the type-inference yourself, all you have to do is look at the source and make deductions. Then, from your deductions, deduce more and more types until all types are known, or until you've found a discrepancy.
To get you started:
In reduce, you're pattern-matching lst against patterns of type 'a list. Thus, lst must be typed as 'a list.
The values after each pattern must have the same type, so u has the same type as f h (reduce f t u).
Et cætera, et cætera...
Related
I'm required to output a pair of lists and I'm not understanding why the pair I'm returning is not of the correct type.
let rec split l = match l with
| [] -> []
| [y] -> [y]
| x :: xs ->
let rec helper l1 acc = match l1 with
| [] -> []
| x :: xs ->
if ((List.length xs) = ((List.length l) / 2)) then
(xs, (x :: acc))
else helper xs (x :: acc)
in helper l []
(Please take the time to copy/paste and format your code on SO rather than providing a link to an image. It makes it much easier to help, and more useful in the future.)
The first case of the match in your helper function doesn't return a pair. All the cases of a match need to return the same type (of course).
Note that the cases of your outermost match are also of different types (if you assume that helper returns a pair).
I'm writing a function in OCaml to check whether two types are unifiable and will produce a unifier if there is one or print the appropriate message.
Here is the type system :
type typExp =
| TypInt
| TypVar of char
| Arrow of typExp * typExp
| Lst of typExp;;
type substitution = (char * typExp) list;;
I wrote a method to perform substitution of a variable by a type expression given substitution rules of type substitution.
let rec substitute (tau1 : typExp) (v : char) (tau2 : typExp) : typExp =
match tau2 with
|TypInt -> TypInt
|TypVar q -> (if(q=v) then tau1 else TypVar q)
|Arrow (q,w) -> Arrow ((substitute tau1 v q), (substitute tau1 v w))
|Lst q -> Lst (substitute tau1 v q)
;;
let rec applySubst (sigma: substitution) (tau: typExp) : typExp =
let reversedList = List.rev sigma in
match reversedList with
|(a,s)::w -> applySubst (List.rev w) (substitute s a tau)
|[]->tau
;;
I used those methods to implement the unifiable check function, however, when two types are not unifiable, it should print a message on the screen and the print method return a unit type not of that of substitution. I don't know how to deal with that.
let unify (tau1: typExp) (tau2:typExp) : substitution =
let rec helper acc t1 t2=
match t1, t2 with
| TypInt,TypInt -> acc(*not the problem*)
| TypInt, TypVar q -> (q,TypInt)::acc
| TypInt, Arrow (a,b) -> print_string "Not Unifyable" (* aproblem here*)
| TypInt, Lst a -> print_string "Not Unifyable"
| TypVar q, TypInt -> (q, TypInt)::acc
| TypVar q, Arrow (a,s) -> (q,Arrow(a,s))::acc
| TypVar q, Lst w -> (q, Lst w)::acc
| TypVar a, TypVar b ->( if(a=b) then acc else (a,TypVar b)::acc)
| Arrow(q,w), Arrow(a,s) -> if (helper [] w s)=[] then []
else helper (helper [] w s) (applySubst (helper [] w s) q) (applySubst (helper [] w s) a)
| Arrow (q,w), TypInt -> print_string "Not Unifyable"
| Arrow (q,w), TypVar a -> (a, Arrow(q,w))::acc
| Arrow (q,w), Lst a -> []
| Lst q, TypInt -> []
| Lst q, TypVar a -> (a,Lst q)::acc
| Lst q, Arrow (s,t) -> []
| Lst q, Lst w -> helper acc q w
in helper [] tau1 tau2
I'm wondering without using option type, is there another way to deal with this?
The issue is due to the fact that the return type of helper is a list of substitution and some of your match do not return this type but the unit type instead. Therefore, the compiler points this error.
Now, one way to fix that is to raise an exception at those point.
exception NotUnifiable;;
And replace all lines similar to :
| TypInt, Arrow (a,b) -> print_string "Not Unifyable"
By :
| TypInt, Arrow (a,b) -> raise NotUnifiable
And the usage of unify:
try
unify ...the arguments...
with NotUnifiable -> print "Not unifiable"
But doing this may not be what you really want : as soon as there is an exception, you stop everything.
If I understand your question, you're trying to decide what value to return when unification isn't possible. This is just a basic design decision for your implementation, so I don't think there's one answer that anyone can give you.
You can definitely change the function's type to substitution option. That is a nice clean solution. The return value of None would indicate that unification isn't possible. These cases would look something like this:
print_string "Not Unifyable"; None
You could also raise an exception for this case. That can be a very effective solution in some cases, as it avoids allocating space for Some for all the successful results (and the work to extract the substitution value). However, the difference in time is usually not worth the extra complexity of dealing with exceptions (in my opinion).
You could also just return an empty list. This feels less clean, as it would be a legitimate result for a null unification (I suspect).
So I have this exercise:
filter (fun x -> x = 0) [(1,0);(2,1);(3,0);(4,1)];;
result int list [1;3]
So basically you have to match your x in fun with the second number in list and if its the same you create new list with the first number.
My solution but is wrong
let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [];;
I get the following error when i want to try the code:
Error: This expression has type int but an expression was expected of
type
int -> bool
I can't reproduce the problem you report. Here's what I see when I try your code:
$ ocaml
OCaml version 4.02.1
# let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [] ;;
val filter : 'a -> ('b * 'a) list -> 'b list = <fun>
# filter 0 [(1,0); (2,1); (3,0)];;
- : int list = [1]
There are no errors, but it gets the wrong answer. That's what I would expect looking at your code.
The error that you are getting is saying that somewhere the compiler is expecting an int -> bool function, but you are giving it an int. The reason you get this error is because you have an equality (f = snd x), where f is of type int -> bool and snd x is of type int. both arguments given to the equality must be of the same type. Instead, what you want to do is simply branch on the result of applying f to the second element of x, such as:
let rec filter f = function
| []->[]
| x::l -> if f (snd x) then fst x :: filter f l else [];;
That said, I would recommend using pattern matching instead of fst and snd, such as:
let rec filter f l =
match l with
| [] -> []
| (x,y)::l -> if f y then x :: filter f l else filter f l
Note that f y will return something of type bool, which will then determine which branch to take.
Altough Matts answer is right. It's good to just reuse existing functions instead of writing a special from the ground up:
[(1,0);(2,1);(3,0);(4,1)]
|> List.filter (fun (_, x) -> x = 0)
|> List.map fst
I have a assignment which requires writing a code to union list without using any library functions
this is my code
let rec union (l1:'a list) (l2:'a list) =
let rec f x l = match l with
| [] -> true
| hd::tl ->
if x = hd then false else f x tl
in
match l2 with
| [] -> l1
| hd::tl ->
if f hd l1 then
union hd::l1 tl
else
union l1 tl
but the compiler said that "This expression has type 'a but an expression was expected of type 'a list The type variable 'a occurs inside 'a list"
can somebody helps me to find out where did I do wrong? thanks
I think you just need some parentheses on the last line:
if f hd l1 then union (hd::l1) tl else union l1 tl
In OCaml function application (as in f x) has very high precedence. So without these parens the expression is interpreted as (union hd) :: (l1 tl).
(This code is pretty nice. Maybe rename f to something more descriptive such as notmem.)
I am working on a project with OCaml and there are some problems regarding to arrays that I am not sure with. I am not allowed to use the List module, so please give me some idea or suggestion with my works.
First, I already implemented a function 'a list -> 'a list called uniq that return a list of the uniq elements in an array, for example uniq [5;6;5;4] => [6;5;4]
Here is my implementation:
let rec uniq x =
let rec uniq_help l n =
match l with
[] -> []
| h :: t -> uniq_help t, n if (n = h) else (h :: (uniq_help(t, n)))
match x with
[] -> []
| h::t -> uniq_help t, h
;;
I mot sure this is a correct implementation, can someone give me some suggestion or correctness?
You functions are syntactically incorrect for various reasons:
uniq_help takes two elements so you have to invoke it using uniq_help t n, not uniq_help(t, n) and the like.
an if/else expression should have the form of if cond then expr1 else expr2.
to use uniq_help locally in uniq, you need an in keyword.
After fixing syntax errors, your function looks like:
let rec uniq x =
let rec uniq_help l n =
match l with
| [] -> []
| h :: t -> if n = h then uniq_help t n else h::(uniq_help t n) in
match x with
| [] -> []
| h::t -> uniq_help t h
However, to be sure that each element is unique in the list, you have to check uniqueness for all of its elements. One quick fix could be:
let rec uniq x =
(* uniq_help is the same as above *)
match x with
| [] -> []
| h::t -> h::(uniq_help (uniq t) h)