Try to understand some weird symbols like ([]:_) in Haskell - list

I have difficulty to understand the following Haskell symbol ([]:_).
I come cross a Haskell function called transpose
transpose::[[Int]]->[[Int]]
transpose ([]:_) = []
transpose x = (map head x):transpose(map tail x)
And I walk through a simple example.
transpose [[1,2],[3,4]]
=>[1,3]:transpose[2,4]
=>[1,3]:[2,4]:transpose[[],[]]
=>[1,3]:[2,4]:[]
=>[[1,3],[2,4]]
It seems to be make sense.
But If I pass [[], [1]] to the function, the output is still []
transpose [[], [1]]
=>[]
Can anyone explain why transpose return [] if I pass [[], [1]]?

This is not a symbol ([]:_) is simply a short version of:
( [] : _ )
^ ^ ^
| | wildcard
| empty list
list construct
The list construction is something like ( h :t ) with h the head (an element) and t the tail (either the remainder of the list, or the empty list). See CONS for more information.
So it means: match a list with as head the empty list and as tail a don't care.
This makes sense, since a transpose is only well defined on rectangular structures. What do you expect the transpose of [[],[1]] should be.
The reason that this line is necessary, is because in the second (recursive) call, you use the tails of all lists.
If you thus calculate the transpose of [[1,2,3],[4,5,6],[7,8,9]], you will first take the recursive case: as head, you emit all the heads of all the lists, so [1,4,7], and the recursion is done with the tails of all the lists, so you call it with transpose [[2,3],[5,6],[8,9]].
In the second round (recursive call), you emit again the heads of the lists, so [2,5,8] and do the recursive call on the tails: [[3],[6],[9]]. Next you emit again the heads [3,6,9], and now the recursive call on the tails is transpose [[],[],[]]. So a list of all empty lists. If the matrix condition hold however, it means we have finished. The pattern ( [] : _) matches [[],[],[]] so it will emit the empty list [].

It's not a matrix! Your first row is empty, therefore the first condition is satisfied and returns empty list as defined.

Related

how to append three lists inside a list

I am trying to figure out is there anyway that i can use append to make the three lists of integer inside a list to become a list of a list of integers, for example
[[1];[2];[3]] -> [[1;2;3]]
[] -> [[]]
[[]] -> []
but i am not sure how loop really in OCaml.
and the below is what i have tried, but i dont think it work
let rec ls (l : 'a list list) =
match l with
| [] -> []
| x :: y -> l#y
i have tried to use # to do function, but i don't how to remove the bracket.
Note that in your attempt, you never use x which is the head of the list, and the function is not recursive. It never calls itself. Note that # is never necessary in this exercise, which is good because it leads to some ugly performance implications.
Consider that you can use pattern-matching to identify whether a list is empty or not, and to extract elements from the head and the tail of a list. What should the result of flattening an empty list be? An empty list.
let rec flatten =
function
| [] -> []
Now, if the first list in the list of lists is empty, it should be the result of flattening the tail. This seems pretty obvious so far.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
Now, if it's not empty then we can cons the first element of the first list onto the result of flattening... I'll leave that as an exercise for you to fill in.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
| (x::xs)::tl -> x :: flatten ...
Looping via recursion
While OCaml does have imperative loops, it is much more idiomatic, especially when dealing with lists, to loop via recursion.
In order to use recursion to loop, there must be at least one exit case where the function does not recursively call itself, but there must also be at least one case where it does, and that function call must in some way update the state being passed in so that it converges on the exit case.
If the exit case is passing in an empty list, the recursive calls must get closer to passing in an empty list on each call or the recursion will never end.
If you did want to append...
If you decided you do like #, and don't care about O(n^2) runtime complexity, you can use it with List.fold_left to readily accomplish this goal.
# List.fold_left (#) [] [[1;2]; [3;4]];;
- : int list = [1; 2; 3; 4]
This is equivalent to [] # [1;2] # [3;4].

Pattern matching on rest of list

I'm trying to pattern match on a list of pairs, where I'm trying to return a list from the list of pair, however I'm having trouble figuring out where to make the recursive call. Without the recursive call I have this:
let countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]
;;
But naturally this only applies to the first pair in the list and simply returns ["countryA"; "countryB"] without the rest of the list.
With the recursive call this simply only returns an empty list:
let rec countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]::countriesInChart tt
;;
How would I make the recursive call such that all the pairs in the list would return as a list?
You have this:
[x;y] :: countriesInChart tt
This says to add a new list of two elements onto the front of a list of lists.
I don't think you want a list of lists, you just want a list. So you shouldn't be making a list of two elements.
If x and y are the same type (as I suspect they are), what you probably want is this:
x :: y :: countriesInChart tt
This says to add both x and y individually to the front of the recursively generated list.
You can also write this, which is completely equivalent:
[x; y] # countriesInChart tt
However, this constructs a list of two elements only to throw it away. So it's a tiny bit of extra work for no benefit.

F# return list of list lengths

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.

How to use if-then-else in a recursive function

I am writing a function that will take a list of list and merge it into sorted pairs of list. For example [[1],[9],[8],[7],[4],[5],[6]] would return [[1,9],[7,8],[4,5],[6]]. This is my first attempt at SML. I keep getting this error: operator and operand don't agree [overload conflict].
fun mergePass[] = []
| mergePass(x::[]) = x::[]
| mergePass(x::y::Z) =
if x<y
then (x # y)::mergePass(Z)
else (y # x)::mergePass(Z);
Edit: If mergePass is called on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]].
This merge function takes two sorted lists
fun merge([],y) = y
| merge(x,[]) = x
| merge(a::x,b::y) =
if a < b then a::merge(x,b::y)
else b::merge(a::x,y);
You seem reasonably close. A few hints/remarks:
1) Aesthetically, using nil in one line and [] in others seems odd. Either use all nil or use all []
2) Since the input are lists of lists, in x::y::z, the identifiers x and y would be lists of integers, rather than individual integers. Thus, x<y wouldn't make sense. You can't compare lists of integers using <.
3) Your problem description strongly suggests that the inner-lists are all 1-element lists. Thus you could use the pattern [x]::[y]::z to allow you to compare x and y. In this case, x#y could be replaced by [x,y]
4) If the inner lists are allowed to be of arbitrary size, then your code needs major revision and would probably require a full-fledged sort function to sort the result of concatenating pairs of inner lists. Also, in this case, the single list in the one inner list case should probably be sorted.
5) You have a typo: mergeP isn't mergePass.
On Edit:
If the sublists are each sorted (and the name of the overall function perhaps suggests this) then you need a function called e.g. merge which will take two sorted lists and combine them into a single sorted list. If this is for a class and you have already seen a merge function as an example (perhaps in a discussion of merge-sort) -- just use that. Otherwise you will have to write your own before you write this function. Once you have the merge function, skip the part of comparing x and y and instead have something as simple as:
| mergePass (xs::ys::zss) = (merge xs ys) :: mergePass zss
If the sublists are not merged, then you will need a full-fledged sort in which case you would use something like:
| mergePass (xs::ys::zss) = sort(xs # ys) :: mergePass zss

SML: How can I pass a function a list and return the list with all negative reals removed?

Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t