foldl operation in sml - sml

I would appreciate if someone could guide me here, I really want to understand what I did wrong and why?
This is my code:
fun get_longest xs = foldl((fn (x ,y ) => if String.size x >= String.size y then x
else y),[],xs)
My function should take a list of strings and return the longest string; if the list is empty, just return [].
But I'm getting this error:
Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z * 'Y -> 'Y
operand: (string * string -> string) * int * 'X
in expression:
foldl ((fn (<pat>,<pat>) => if <exp> then <exp> else <exp>),0,xs)
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:296.17-296.20

Take a look at the signature of foldl:
val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
You can see that your function should have the form
fun get_longest xs = foldl foo acc xs
where foo is the function applies on an element and an accumulator and acc is the initial accumulator.
Hints:
Since get_longest returns a string, the accumulator should have type string. Your job is to find out a suitable string to fill in. Note that the value [] you want here doesn't make sense.
xs is a string list, your foo function should have type string * string -> string. Now you have to replace foo by an appropriate anonymous function.

foldl is a curried functions, it's type is ('a * 'b -> 'b) -> 'b -> 'a list -> 'b. Therefore it should be called as foldl f s xs. You're calling it as foldl (f, s, xs). That's wrong because it calls foldl with a tuple as its argument and foldl does not expect a tuple. If it did, its type would be ('a * 'b -> 'b) * 'b * 'a list -> 'b.

Related

Writing the Z combinator in Ocaml

I'm new to lambda calculus, and I find the grammar sometimes ambiguous to me.
Specifically, I'd like to know how to understand the Z combinator:
Z = λ f. (λ x. f (λ v. xxv)) (λ x. f (λ v. xxv))
How to write it in OCaml?
Updated:
I get error when writing like this:
fun f-> let g = fun x -> f(fun v-> x x v)in g g;;
Error: This expression has type 'a -> 'b -> 'c
but an expression was expected of type 'a
The type variable 'a occurs inside 'a -> 'b -> 'c
Typing the Z-combinator requires either to allow recursive types (with the -rectypes option) or to box the type recursion inside a type constructor:
type 'a fix = Fix of ('a fix -> 'a)
let z f =
(fun (Fix x as fx) -> f (fun v -> x fx v))
(Fix (fun (Fix x as fx) -> f (fun v -> x fx v)))
Essentially, we are replacing
x x v
which requires x to accept itself as an argument which leads to the recursive type 'a -> 'b -> 'c as 'a by
x fx v
which boxes the recursive type as ('a -> 'b) fix -> 'a -> 'b

SML: Interpret function from its type

I am new to SML (meta-language).
Can anyone tell me how to derive the function from the type given as below:
(’a -> ’b) -> (’b list -> ’c) -> ’a -> ’c list
I am having a hard time in understanding the curried functions in SML.
This will work
- fun f g h x = [h [g x]];
> val ('a, 'b, 'c) f = fn : ('a -> 'b) -> ('b list -> 'c) -> 'a -> 'c list
Here's how I did it.
We are given the type
('a -> 'b) -> ('b list -> 'c) -> 'a -> 'c list
So we know we want a function with three curried arguments, the first two are functions, and the third is anything. So we write:
fun f g h x = ....
Now the first argument is a function that takes in something of type 'a, which x is so we want a
g x
on the right hand side. That will be of type 'b. Now h takes in a 'b list, so we can write
h [g x]
This produces a value of type 'c, but we want f to return a 'c list so we just put that in a list, so we get:
fun f g h x = [h [g x]];

This expression has type 'a list but an expression was expected of type 'a

I have a function in OCaml which should merge two lists:
let rec merge (list1, list2) =
match (list1, list2) with
([], []) -> merge (List.tl list1, List.tl list2) :: List.hd list1 :: List.hd list2
|(_, []) -> merge (List.tl list1, list2) :: List.hd list1
|([], _) -> merge (list1, List.tl list2) :: List.hd list2;;
but for some reason the compiler doesn't let this code through exitting with:
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
How can I specify that these are lists of 'a I'm trying pass, not 'a?
First of all, this function won't work. If the two lists are empty you merge the tail and concatenate the head of each of them but...well...they are empty...
Anyway, your problem is that you're using the :: operator (concatenation) whose type is 'a -> 'a list -> 'a list so the left member should be an element and the right one a list, here the left one is the list and the right one the element so it can not work.
About your question, since the type is inferred, you can't tell the compiler that you're right and he's wrong, in this case the error was truly explicit :
List.tl l (* 'a list *) :: List.hd l (* 'a *)
will always return an error because you have an infinite type (since :: is of type 'a -> 'a list -> 'a list, I let you try to determine a finite type 'a that could match with your concatenation)
So, I guess what you want to do is something like this :
let rec merge (list1, list2) =
match list1, list2 with
| [], _ -> list2;;
| hd :: tl, _ -> hd :: merge tl list2

OCaml type error for lists

I want to write a function that will combine all the elements in a list in OCaml. Simple enough, so far I have a working function:
let rec comAll (f : 'a -> 'a -> 'a) (r : 'a) (l : 'a list) : 'a =
match l with [] -> r
| hd::tl -> let comAll2 = comAll f r tl in f hd comAll2
;;
The First argument is a function, the second is a default value to return when/if the input list is empty, and the third argument is the list itself.
This function works as intended, except when I try to call it using another function, for example:
let inList (l : 'a list) (e : 'a) : bool = comAll (fun x y -> if x == e then true else y) false l ;;
which will pass as a function, returning inList : bool list -> bool -> bool = <fun> however, I want to instead have it return inList : 'a list -> 'a -> bool = <fun>
I have tried instead defining comAll as: let rec comAll f r l =... and that works, but I want to declare the function with explicit types.
Any help or guidance on what I am doing incorrect here?
You are declaring your parameter f to be of type 'a -> 'a -> 'a but you want to pass a function of type 'a -> bool -> bool. In other words, you want to have two different types. You should declare f to be of type 'a -> 'b -> 'b. The rest will follow.
# let rec comAll (f : 'a -> 'b -> 'b) (r : 'b) (l : 'a list) : 'b =
match l with [] -> r
| hd::tl -> let comAll2 = comAll f r tl in f hd comAll2 ;;
val comAll : ('a -> 'b -> 'b) -> 'b -> 'a list -> 'b = <fun>
# let inList (l : 'a list) (e : 'a) : bool =
comAll (fun x y -> if x == e then true else y) false l;;
val inList : 'a list -> 'a -> bool = <fun>

Type of a function in SML

Can anyone explain to me why the type of the function given below is
('a * 'b -> 'b) -> 'b -> 'a list -> 'b?
The function is:
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
When I look at this function, I find the type should just be ('a * 'b -> 'b) -> 'b since we have a function f which is taking in a tuple and just returning at 'b and also in the base case we return the 'b.
To determine the type of a function, the process basically goes like this:
Given a function,
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
assume all types of the parameters and return value are unknown.
foldr : 'a -> 'b -> 'c -> 'd
f (arg1): 'a
b (arg2): 'b
(arg3): 'c
(return): 'd
fun foldr f b [] = b
First of all, we can see that b (arg2) is the same as the return type of foldr (return) and (arg3) is a list of some unknown type.
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
| foldr f b (x::xs)
x and xs make up the list of (arg3).
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
= f (x, (foldr f b xs))
Then f (arg1) is a function that takes a 2-tuple and returns the same type as foldr returns (return). The first item of the tuple is the same type of x. The second item of the tuple is the same type of the return type of foldr (return). The types also hold so far for the recursive call to foldr.
f (arg1): 'e * 'b -> 'b
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
It cannot be simplified any further so we have the type:
foldr: ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
I think that the above code for foldr is incorrect; it should be
fun foldr f b [] = b
| foldr f b (x::xs) = (f x (foldr f b xs))
That is, it should not be passing in a tuple of arguments, but rather passing in the accumulator and the recursive call to foldr as arguments as usual.
As for where the type comes from, remember that foldr takes in three parameters:
The function to apply over the range.
The initial value of the accumulator.
The range over which to fold.
Let's say that the accumulator has type 'b and that the list has type 'blist. We know that the overall return type of the function should be 'b, because we have
fun foldr f b [] = b
Let's now see what the type of f is. We have this:
foldr f b (x::xs) = (f x (foldr f b xs))
This takes in the first element of the list and the accumulator, then produces something that must be of type 'b. The list has type 'a list and the accumulator has type 'b, so the function has type ('a * 'b -> 'b).
Summing this up, the type of the function is
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
Which is what is being reported.