I asked this question a few days ago but now I have more understanding on the subject. But I still get problem that operator and operand dont agree:
Using ListPair.foldr I need to create a function zipWith that combines pairwise two lists. The type of the overall function should be:
zipWith : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list
ListPair.foldr : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
- zipWith (fn (x, y) => x + y) [1,2,3,4] [10,20,30,40];
val it = [11,22,33,44] : int list
My attempt:
fun zipWith xs ys = ListPair.foldr(zipWith(x,y,z) => (x+y)::z) 0 xs ys
There are several things wrong in your attempt:
The parameters. You have zipWith xs ys, but the type says that the first parameter has to be a function, so change that to zipWith f xs ys.
You're calling zipWith recursively. ListPair.foldr takes care of that for you, though, so don't.
You're giving ListPair.foldr 0 as its starting value. Fold-functions always take a starting value of the same type as the return value - we want zipWith to return a list, so the fold-function should take a list as its starting value. The empty list, that is.
Think about how ListPair.foldr works. We can do it one parameter at a time. The type of ListPair.foldr is:
fn : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
The first parameter is a function with the type:
fn : 'a * 'b * 'c -> 'c
Let's make a toy function as an example:
fun foo (a, b, acc) = a+b :: acc
This function takes two numbers and a list, adds the two numbers together, puts them in front of the list, and returns it. The type is:
fn : int * int * int list -> int list
Which corresponds nicely with our type signature from the first parameter of ListPair.foldr.
Now, let's look at the type of ListPair.foldr foo.
fn : int list -> int list * int list -> int list
The next parameter is an int list - the starting value for the folding. Great, we already figured out that this is the empty list. The type of ListPair.foldr foo [] is:
fn : int list * int list -> int list
The last parameter is a tuple containing two lists. We put in some random lists, and try it out in an sml interpreter:
- ListPair.foldr foo [] ([1,2,3],[10,20,30])
> val it = [11, 22, 33] : int list
Now, all you need to do is to replace the parameters to ListPair.foldr (foo and the two random lists) with parameters from zipWith, and you're done.
Related
Say I have the following
module IntPairs =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
0 -> Stdlib.compare y0 y1
| c -> c
end
module PairsMap = Map.Make(IntPairs)
And I add a few elements:
let m = PairsMap.(empty |> add (1,1) 1 |> add (2,1) 1 |> add (1,2) |> add (2,2))
How would i use to_seq to print keys in ascending order?
I'm not to familiar with iterators in ocaml
This is more of a request for OCaml tutoring than a question about a specific problem in your code. It would generally be faster to read the documentation than to ask individual questions here on StackOverflow.
With that said, the Seq interface looks like this:
type 'a t = unit -> 'a node
and 'a node = Nil | Cons of 'a * 'a t
val empty : 'a t
val return : 'a -> 'a t
val map : ('a -> 'b) -> 'a t -> 'b t
val filter : ('a -> bool) -> 'a t -> 'a t
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
val iter : ('a -> unit) -> 'a t -> unit
As you can see, it offers many higher-order traversal functions. The one you would want to use is probably iter since you want to print the values rather than calculate with them. I.e., there is no return value for your desired usage.
However, you should note that the Map interface already has an iter function. As near as I can tell, there's no reason to convert to a sequence before doing your iteration. The Map.iter documentation says this:
The bindings are passed to f in increasing order with respect to the ordering over the type of the keys.
This is what you want, so Map.iter seems like it will do the trick.
PairsMap.iter my_print_function m
I have the following function table which takes a list of tuples (x's are strings and y's are a list of strings) and I want to return a tuple of x1 and the length of the list y1. I tried it with this simple function:
let rec table lst = function
| [] -> []
| [(x1, y1, x2, y2)] -> [(x1, (List.length y1))]
| (x1_h, y1_h, x2_h, y2_h) :: tail -> (x1_h, (List.length y1_h))::(table tail)
But the following error occured:
Error: This expression has type
('a * 'b list * 'c * 'd) list -> ('a * int) list
but an expression was expected of type ('a * int) list
I'm not really sure what I did wrong there.
function takes an argument implicitly and pattern matches on that. In other words:
let f = function | ...
is equivalent to
let f lst = match lst with | ...
So when you write
let rec table lst = function | ...
That translates to
let rec table lst lst2 = match lst2 with | ...
The error points to the recursive call, table tail, because it is partially applied and returns a function ('a * 'b list * 'c * 'd) list -> ('a * int). table tail tail would return ('a * int list) as expected and is completely valid. But since lst is unused in your function, you can just remove it instead.
This question already has an answer here:
Swap pairs of elements in a list using pattern matching
(1 answer)
Closed 5 years ago.
I am trying to write a function to swap a pair of tuples inside of a list like this:
- pairSwap [(1, 2), (3, 4), (5, 6);
[(2,1),(4,3),(6,5)]
I am having a hard time figuring out what I am doing wrong with my syntax while declaring the function. This is what I have so far:
fun pairSwap ((a : 'a, b: 'a) list) : (('a, 'a) list) =
...
;
Where am I going wrong?
Edit:
Solution
fun pairSwap (t : ('a * 'a) list) : ('a * 'a) list =
if null t
then []
else
let
val v = hd t
in
(#2 v, #1 v)::pairSwap (tl t)
end
;
Since you have provided a solution in the meantime, here is some feedback on it:
You don't really need the type annotations. You can let type inference do the work.
fun pairSwap t = ...
You can use null, hd and tl, but consider pattern matching:
fun pairSwap [] = []
| pairSwap ((x,y)::ps) = (y,x)::pairSwap ps
This also makes the let-expression redundant.
As Matt points out, the type for this function is ('a × 'b) list → ('b × 'a) list, which means you can also swap pairs where the left side has a different type ('a) than the right side ('b), e.g.:
- pairSwap [("hello",42),("world",43)];
val it = [(42,"hello"),(43,"world")] : (int * string) list
You need to pull the variable out of the pair type annotation:
fun pairSwap (arg : ('a * 'b) list) : ('b * 'a) list = ...;
Note that I've also changed it from what you had to what the title requested: ('a * 'a) list -> ('a * 'a) list to ('a * 'b) list -> ('b * 'a) list
(*function f's definition*)
fun f l j y = l j y
val f = fn : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c
What does the below line say about the function f ?
val f = fn : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c
To answer this question it helps to rename your identifiers:
fun apply g x y = g x y;
val apply = fn : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c
apply is equivalent to what you are calling f. What apply does, informally, is take a function, g, of two variables (in curried form) and two arguments x,y and actually applies g to those arguments.
As an example g, define:
fun sum x y = x + y;
val sum = fn : int -> int -> int
Then, for example:
apply sum 5 7;
val it = 12 : int
In the type signature of apply the part
('a -> 'b -> 'c)
is the type of g. It is polymorphic. You can apply any function to arguments of an appropriate type. When you actually use apply (as I did above with sum) then the SML compiler will have enough information to figure out what concrete types correspond to the type variables 'a, 'b, 'c. the overall type of apply is
('a -> 'b -> 'c) -> 'a -> 'b -> 'c
which says that apply is a function which, when fed a function of type ('a -> 'b -> 'c) and arguments of type 'a and 'b, produces a result of type 'c. I'm not sure of any immediate use of apply, though it does serve to emphasize the perspective that functional application is itself a higher-order function.
I prepare for GATE Exam. one of the oldest question is unfamiliar with us. some experts please clarify this for us.
Which of the following can be a type for following ML function ?
my f(g, nil)=nil | f(g,x::xs)=(fn a ⇒ g(a,x))::f(g, xs);
1) (int *book → real) * bool list → (int → real) list
2) (bool *int → int) * real list → (bool → int) list
3) (int *int → real) * real list → (real → bool) list
4) (bool *real → int) * int list → (int → int) list
The Answer Sheets say (1) Is corrects. comments or short description for better understanding?
One of the first things you should do is rewrite the function definition yourself. This will force you to actually parse and understand it.
fun f (g, nil) = nil
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
So, f is a function, even the question says that, it must have type ... -> ...:
val f : ... -> ...
What does it receive? Let's take a look at the first pattern of the function:
fun f (g, nil) = nil
It's something of the form (a, b), which is a 2-tuple. The function's argument must be a tuple then:
val f : (... * ...) -> ...
Just by looking at the definition, we can't figure out what type g must have, but it uses nil for the second element of the tuple and nil is the empty list. That means the second component of the tuple must be a list of something:
val f : (... * ... list) -> ...
What else can we deduce? The return value is nil as well, which means that the function returns a list of something, unclear what that something is yet.
val f : (... * ... list) -> ... list
Ok, let's jump to the second pattern of the function definition now:
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
We don't find anything more about the type of the argument, we just got confirmation that the second element of the tuple must indeed be a list, because it uses the :: constructor.
Let's take a look at the body:
(fn a => g (a, x)) :: f (g, xs)
It looks like it's building a list, so it must return a list, which is in accordance with the return type we've sketched so far, i.e., ... list. Let's
try to figure out the type of elements.
It seems to add a function object as the head of the list built by recursively calling the function f, which we're currently investigating. So the elements of the list we're returning must be functions:
val f : (... * ... list) -> (... -> ...) list
What does that function do, though? It calls g with a 2-tuple argument. Now we can fill in some information about the first element of the 2-tuple f receives. It must be a function that receives a 2-tuple as well:
val f : (((... * ...) -> ...) * ... list) -> (... -> ...) list
Can we say anything about the a parameter received by the function literal added to the return list? Not really, just that it's passed to g. Can we tell anything about the type of x? Not really, just that it's passed to g. Moreover, is there any constraint between a and x? Doesn't look like it. So far, we can only tell that g's type must be looking something like this:
('a * 'b) -> 'c'
Where 'a, 'b and 'c are polymorphic types, i.e., any concrete type can satisfy them. You can view them as wholes. We can now fill in more of the type for the f function:
val f : ((('a * 'b) -> 'c) * ... list) -> (... -> ...) list
We can do more actually, we've already assign a type to the x variable, but that comes from the second argument of the 2-tuple received by f, so let's fill in that too:
val f : ((('a * 'b) -> 'c) * 'b list) -> (... -> ...) list
And we can even fill in the element type of the returned list, because we've already assigned types for that, too.
val f : ((('a * 'b) -> 'c) * 'b list) -> ('a -> 'c) list
We can remove some extra parenthesis from the type we came up with without changing the meaning, because of the type operator precedence rules:
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
Now, our function's type is complete. However, this type can't be found in the list of possible answers, so we'll have to see if any of them can be used instead of what we've determined. Why? Because our function type uses type variables, which can be filled in by concrete types. Let's take them one by one:
Choice 1
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (int * bool -> real) * bool list -> (int -> real) list
It looks like 'a could be int, 'b could be a bool (it's book in what you've pasted, but I'm assuming it was a typo) and 'c could be a real. All the replacements match these correspondences, so we declare that, yes, the first choice can be a possible type for the given function, even though not the most general. Let's take the second choice:
Choice 2
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (bool * int -> int) * real list -> (bool -> int) list
The type-variable to concrete -type correspondence table could be this:
'a -> bool
'b -> int
'c -> int
'b -> real
We can stop here because we can see that 'b was assigned to different types, so this function signature can't be assigned to the implementation we've been given.
Choice 3 and 4
They are similar to choice 2, but I'll let them as an exercise to the reader :)