I already know that foldright (+) [1;2;3;4;5] 0 will just sum up the element from right to left using 0 as the accumulator.
Now, suppose list_obj a list of objects, where each object has 4 methods, i.e. method1, method2, method3 and method4. Each of these methods takes no argument and return an integer.
I would like to create a function taking two arguments, i.e. a list and a method.
let sum liste methode = foldright (+) (map (fun obj -> obj#methode) liste) 0
The purpose of this function is to sum up 4 lists depending on the method used.
So I need to do something like
print_int(sum list_obj method1)
print_ing(sum list_obj method2)
print_int(sum list_obj method3)
print_int(sum list_obj method4)
I know the programming behind it is wrong. How can I do it anyway?
Methods are not values, they cannot be passed as arguments to function like C++'s method pointers. Consequently in:
let sum liste methode = foldright (+) (map (fun obj -> obj#methode) liste) 0
the two occurrences of methode are completely unrelated from the point of view of the compiler
For your use case, you can use a getter function:
let sum getter list = List.fold_left (+) 0 (List.map getter list)
let () =
print_int ## sum (fun obj -> obj#method1) l_obj;
print_int ## sum (fun obj -> obj#method2) l_obj
Related
I have tried to write code but this only returns max value and not the absolute.
let rec maxAbsolutenumber_L l =
match l with
|[] -> None
|x::_ -> x
|x::xs -> max x (max_number_list xs)
Imagine you had a function like max except it returns whichever of the two values has the largest absolute value. Seems like that would solve your problem.
You can start, then, by writing this function.
As a side comment, it is not legitimate to return None for some calls to a function and an integer value for other calls. They aren't the same type.
As another side comment, the second case of your match will match all nonempty lists. I think you want it to match only lists of length 1. The pattern for such a list is [x] (or you can use x :: [], which is equivalent).
Update
Here is the basic structure for defining a function that has another (helper) function inside:
let myfunc a b =
let helper x y =
(* Definition of helper *)
in
(* Definition of myfunc with calls to helper *)
Here's a concrete example, a function that returns the longest string in its input list:
let longest_string strings =
let max_string a b =
if String.length a >= String.length b then a else b
in
List.fold_left max_string "" strings
Here is an implementation of the usual max function, which might give you some ideas for writing similar functions:
let max a b =
if a >= b then a else b
I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.
Problem:Define the function mapf whose first argument is a unary function, and second argument list. The result is a list of the function applied to each element of the argument list. Write a one-liner using fold_right, and not a recursive function.
Solution:
let mapf fn list = fold_right (fun h t -> fn h :: t) list []
I don't understand how that solves the problem because fold_right computes a function with the list arguments in a recursive way, so it returns a value and not a list. I neither understand what the following notation means:
fun h t -> fn h :: t
Your two questions are related. It's true that fold_right returns a value, but a list is a value!
The :: operator adds a new element to the beginning of a list. So the value computed by this application of fold_right is indeed a list.
Another way to think of this might be as follows. If you use fold_right with the + operator you compute a value like so:
fold_right (+) [1; 2; 3] 0 =>
1 + 2 + 3 + 0 =>
6
If you use fold_right with the :: operator, you compute a value like so:
fold_right (::) [1; 2; 3] [] =>
1 :: 2 :: 3 :: [] =>
[1; 2; 3]
This isn't theoretical, it works exactly like this in the REPL:
# List.fold_right (+) [1; 2; 3] 0;;
- : int = 6
# List.fold_right (fun a b -> a :: b) [1; 2; 3] [];;
- : int list = [1; 2; 3]
(You need to write fun a b -> a :: b because the :: notation can't actuallly be used as a stand-alone function. Unfortunately.)
Note that it's completely legitimate to write a list using the :: operator yourself:
# 1 :: 2 :: 3 :: [];;
- : int list = [1; 2; 3]
Update
First, fun x y -> expr is the notation for a "lambda" in OCaml, i.e., for a function literal.
The function fun h t -> fn h :: t takes two values h and t. It applies the function fn to h, and returns a new list with this new value at the front of t.
From a typing standpoint, the value h must be the right type to pass to fn, and fn must return a value of the right type to be in the list t.
You could parenthesize it like this: fun h t -> (fn h) :: t, if that makes it clearer.
The function fun a b -> a :: b is similar except that it just puts a directly onto the list b. It doesn't apply any function. In essence, it does just what the :: operator does.
From a typing standpoint, a has to be the right type to be an element of the list b.
Update 2
If you're trying to understand what a lambda is, one way of looking at it is that it's just a handy way to write a function that's reasonably small. You can easily write your given code without the lambda:
let mapf fn list =
let helper h t = fn h :: t in
List.fold_right helper list []
Instead of a lambda, this version has a locally declared function named helper.
Another way of looking at it is that all functions are lambdas. The idiomatic way of writing a function:
let f x y = x + y
is just a handy abbreviation for a version with an explicit lambda:
let f = fun x y -> x + y
So, really, a lambda isn't a special kind of function. It's exactly like any other function. It's just a notational choice.
I'm having trouble using list pattern with multiple parameters. For example, trying to define:
somefunction (x:xs) (y:ys) = x:[y]
results in Occurs check: cannot construct the infinite type: t0 = [t0].
Basically, I want to take two lists as parameters to a function and manipulate each of them using the (x:xs) pattern matching approach. Why is this wrong and how can I do it right? Thank you much!
EDIT: Update with more code as suggested was needed in answers.
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
EDIT 2: Missed an important update. The error I'm getting with the above code is Occurs check: cannot construct the infinite type: t0 = [[t0]]. I think I understand the problem now.
Your function snippet is perfectly sound:
(! 514)-> ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let f (x:xs) (y:ys) = x:[y]
Prelude> :type f
f :: [a] -> [a] -> [a]
But the context contradicts that type, and the type inference give you that error. For instance, I can create a context that will give this error:
Prelude> let g xs ys = xs : ys
Prelude> :type g
g :: a -> [a] -> [a]
And then if I combine f and g like below, then I get your error:
Prelude> let z x y = g x (f x y)
<interactive>:7:20:
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `f', namely `x'
In the second argument of `g', namely `(f x y)'
In the expression: g x (f x y)
Prelude>
To understand you error properly, you will need to examine (or post) enough context.
The problem is with all 3 lines taken together:
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
None of them are incorrect taken on their own. The problem is that the three equations are inconsistent about the return type of somefunction.
From the last equation, we can see that both arguments are lists (since you pattern match on them using the list constructor :).
From the last equation, we can see that the return type is a list whose elements must be the same type as the elements of the argument lists (which must also both be the same type), since the return value is x:[y] (which is more often written [x, y]; just the list containing only the two elements x and y) and x and y were elements of the argument lists. So if x has type t0, the arguments to somefunction both have type [t0] and the return type is [t0].
Now try to apply those facts to the first equation. a must be a list. So [a] (the list containing exactly one element a) must be a list of lists. And then [a]:[] (the list whose first element is [a] and whose tail is empty - also written [[a]]) must be a list of lists of lists! If the parameter a has type [t0] (to match the type we figured out from looking at the last equation), then [a] has type [[t0]] and [a]:[] (or [[a]]) has type [[[t0]]], which is the return type we get from this equation.
To reconcile what we learned from those two equations we need to find some type expression to use for t0 such that [t0] = [[[t0]]], which also requires that t0 = [[t0]]. This is impossible, which is what the error message Occurs check: cannot construct the infinite type: t0 = [[t0]] was about.
If your intention was to return one of the parameters as-is when the other one is empty, then you need something more like:
somefunction a [] = a
somefunction [] b = b
somefunction (x:xs) (y:ys) = [x, y]
Or it's possible that the first two equations were correct (you intend to return a list of lists of lists?), in which case the last one needs to be modified. Without knowing what you wanted the function to do, I can't say.
May be you want to write:
somefunction xs [] = xs
somefunction [] ys = ys
somefunction (x:xs) (y:ys) = x : y : []
You have extra brackets. And your definition of x : y not contains []. So compiler think, y is already a list
I need a function that recursively returns (not prints) all values in a list with each iteration. However, every time I try programming this my function returns a list instead.
let rec elements list = match list with
| [] -> []
| h::t -> h; elements t;;
I need to use each element each time it is returned in another function that I wrote, so I need these elements one at a time, but I can't figure this part out. Any help would be appreciated.
Your function is equivalent to :
let rec elements list =
match list with
| [] -> []
| h :: t -> elements t
This happens because a ; b evaluates a (and discards the result) and then evaluates and returns b. Obviously, this is in turn equivalent to:
let elements (list : 'a list) = []
This is not a very useful function.
Before you try solving this, however, please understand that Objective Caml functions can only return one value. Returning more than one value is impossible.
There are ways to work around this limitation. One solution is to pack all the values you wish to return into a single value: a tuple or a list, usually. So, if you need to return an arbitrary number of elements, you would pack them together into a list and have the calling code process that list:
let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ()) (* Print four values *)
Another less frequent solution is to provide a function and call it on every result:
let my_function action =
action 1 ;
action 2 ;
action 3 ;
action 4
in
my_function print_int
This is less flexible, but arguably faster, than returning a list : lists can be filtered, sorted, stored...
Your question is kind of confusing - you want a function that returns all the values in a list. Well the easiest way of returning a variable number of values is using a list! Are you perhaps trying to emulate Python generators? OCaml doesn't have anything similar to yield, but instead usually accomplishes the same by "passing" a function to the value (using iter, fold or map).
What you have currently written is equivalent to this in Python:
def elements(list):
if(len(list) == 0):
return []
else:
list[0]
return elements(list[1:])
If you are trying to do this:
def elements(list):
if(len(list) > 0):
yield list[0]
# this part is pretty silly but elements returns a generator
for e in elements(list[1:]):
yield e
for x in elements([1,2,3,4,5]):
dosomething(x)
The equivalent in OCaml would be like this:
List.iter dosomething [1;2;3;4;5]
If you are trying to determine if list a is a subset of list b (as I've gathered from your comments), then you can take advantage of List.mem and List.for_all:
List.for_all (fun x -> List.mem x b) a
fun x -> List.mem x b defines a function that returns true if the value x is equal to any element in (is a member of) b. List.for_all takes a function that returns a bool (in our case, the membership function we just defined) and a list. It applies that function to each element in the list. If that function returns true for every value in the list, then for_all returns true.
So what we have done is: for all elements in a, check if they are a member of b. If you are interested in how to write these functions yourself, then I suggest reading the source of list.ml, which (assuming *nix) is probably located in /usr/local/lib/ocaml or /usr/lib/ocaml.