I am learning Haskell currently and running into a problem where I am trying iterate through a list but I need the ability to return to the start of the list. For instance, if my list of tuples is is:
[(1,5), (4,3), (5,6), (1,7), (7,9), (3,11)]
I need to go from 1 to 4 to 5... I am doing this currently by recursively calling my function on the tail of the list. This works as it should but here is the problem:
I am matching the numbers to another list of tuples. So for instance, my second list would be something like
[(6,10)]
So Neither 1 or 5 match 6 or 10, neither 4 or 3 match 6 or 10 but the 6 from (5,6) matches so I would add it to the front. and now I need to start back at the front of the list. The problem is the way I am iterating, calling the function by calling the tail means I can't see the (1,5), (4,3) I have been struggling to conceptually solve this problem for the better half of a week. I know how to the whole (head list) : function (tail list) but since my return is the new list of matched pairs I can't quite get that to work.
Not sure if that makes sense but in a nutshell after adding the (5,6) to the list I get the result of [(5,6),(6,10)] which is good but when I want to now start checking again it starts with (1,7) instead of (1,5) which would match now.
My code is in pieces right now in the middle of a solution so it would be a giant mess to show. Plus I am really just wanting help trying to conceptualize what I have to do.
EDIT
Ok to clear up some confusion, lets say I have two lists:
list1: [(8,7),(1,5),(8,9),(4,3),(5,6),(1,7),(11,9)]
list2: [(6,10),(10,12)]
I have a function that takes both lists and will return the updated list2. List1 compares the characters in it's tuples with the characters at the front and rear of list2's tuples (I don't want to insert into between as they are linked ...,10)<-->(10,...). So starting off, (8,7) does not match to either the 6 or 12 so I move on. Now when I move on I am calling back my function and passing it the tail of list1.
for instance:
master list1 list2
| comparisons.... = master (tail list1) (addToList list2)
.
.
.
| otherwise = master (tail list1) list2
I am not writing out all the comparisons to save space but they all work fine and it goes through the list as it should except for one part. Back to the list, I now have (1,5) which against doesn't match so I pass off the tail and get to (8,9), again nothing so I progress, (4,3) doesn't match so I get to (5,6) which does match, I can flip it and add it to the front to make [(5,6),(6,10),(10,12)] and now I would remove (5,6) from list1 as I already added it to list2. The problem is now I Would again pass the tail and be on (1,7) and then (11,9) which would then end the program because we are at the end of the list.
My desired output would be [(11,9),(9,8),(8,7),(7,1),(1,5),(5,6),(6,10),(10,12)] instead of [(5,6),(6,10),(10,12)]
Again, code isn't really going to help me I just want someone to offer up a different way to think of it. This is my first time touching a functional language and to say I am confused at parts is an understatement.
Since you're learning Haskell, I guess you probably want to solve this problem yourself, so let me show you how might solve a simpler variation. Let's say we have a list of words, and we want to build a new list of words where, for each adjacent pair, the last letter of the first word in the pair matches the first letter of the last word. However, we'll only add words to the end of our list (unlike your example where you can add pairs to the beginning or end, or maybe even somewhere in the middle -- it wasn't clear from your description).
So, if we start with a list of words:
["cat","bat","cow","war","rot","tar"]
and a "seed" list:
["tub"]
then we'd like:
link ["cat","bat","cow","war","rot","tar"] ["tub"]
to give:
["tub","bat","tar","rot"]
Here, starting with the list ["tub"], we've found the first word that starts with a "b", so we can add it to the end to get ["tub","bat"], then we search for the remaining first word that starts with "t" to get ["tub","bat","tar"], and then we search for the first remaining word that starts with "r" to get ["tub","bat","tar","rot"], and then the program ends because there are no remaining words that start with "t".
Our first try (which I think is similar to your algorithm above) might be:
link :: [String] -> [String] -> [String]
link (wrd:wrds) chain
| lastLetter == head wrd = link wrds (chain ++ [wrd])
| otherwise = link wrds chain
where lastLetter = last (last chain)
link [] chain = chain
Unfortunately, this gives the wrong answer:
> link ["cat","bat","cow","war","rot","tar"] ["tub"]
["tub","bat","tar"]
>
It misses "rot" because it only processes the tail of the list of words after adding "tar", and there are no more words left. You need it to go back to the beginning of the list, and this is where you're stuck.
The problem is that, when you get the first successful match on "bat", the recursive call is:
link wrds (chain ++ [wrd])
=
link ["cow","war","rot","tar"] (["tub"] ++ ["bat"])
instead of:
link wrds (chain ++ [wrd])
=
link ["cat","cow","war","rot","tar"] (["tub"] ++ ["bat"])
You somehow need to include the list of unmatched words you've already processed (namely ["cat"]) as well as the tail of the list of words (starting with "cow").
In Haskell, if you need some information (like the "list of unmatched words you've already processed), you usually pass it along as an extra parameter. So, let's rewrite link to take that extra list:
link' :: [String] -> [String] -> [String] -> [String]
link' unmatched (wrd:wrds) chain = ...
with the idea that the initial list of unmatched words will be empty:
> link' [] ["cat","bat","cow","war","rot","tar"] ["tub"]
Now, let's figure out the definition of link'. We'll start with the easiest case, the "otherwise" case, where we did not match on the current wrd. In this case, we add wrd to the list of unmatched words and continue looking in the rest of the wrds:
... | otherwise = link' (unmatched ++ [wrd]) wrds chain
On the other hand, if we do match, we want to add the word to the chain:
... | lastLetter == head wrd = link' ?? ?? (chain ++ [wrd])
but what should the first two arguments be? Well, we want to start fresh, looking through all the words in the list except the wrd we matched. That is, we want to look through all the unmatched words, plus the rest of the wrds, so we want:
... | lastLetter == head wrd = link' ?? (unmatched ++ wrds) (chain ++ [wrd])
What about the first argument for this call? Well, we're starting fresh, so there aren't any unmatched words -- the unmatched list should be empty:
... | lastLetter == head wrd = link' [] (unmatched ++ wrds) (chain ++ [wrd])
This gives the complete, updated definition:
link' :: [String] -> [String] -> [String] -> [String]
link' unmatched (wrd:wrds) chain
| lastLetter == head wrd = link' [] (unmatched ++ wrds) (chain ++ [wrd])
| otherwise = link' (unmatched ++ [wrd]) wrds chain
where lastLetter = last (last chain)
What about the terminating case:
link' unmatched [] chain = ???
This is perhaps a little trickier. However, remember that, if we ever match a word, we jump back to the beginning with:
link' [] (unmatched ++ wrds) (chain ++ [wrd])
If there's at least one word left (i.e., if (unmatched ++ wrds) is non-empty), we'll keep going with a non-terminating case. The only way we could get to the terminating case would be if (1) we matched the last available word and jumped back to the "beginning" with an empty word list, or (2) we got to the end of the word list without a match. In either case, the chain is complete -- in case (1), all words in the word list have been successfully added to the chain; in case (2), the word list is non-empty, but none of the words can be successfully added. So, in either case, we want to stop and return the chain, and the terminating case is:
link' unmatched [] chain = chain
When you use an "extra" parameter like this, it's common to wrap things up in a helper function, so the final revised definition of link would look something like this:
link :: [String] -> [String] -> [String]
link wrds chain = link' [] wrds chain
where
link' unmatched (wrd:wrds) chain
| lastLetter == head wrd = link' [] (unmatched ++ wrds) (chain ++ [wrd])
| otherwise = link' (unmatched ++ [wrd]) wrds chain
where lastLetter = last (last chain)
link' unmatched [] chain = chain
This now gives the right answer:
> link ["cat","bat","cow","war","rot","tar"] ["tub"]
["tub","bat","tar","rot"]
>
Related
I have just started to learn ocaml and I find it difficult to extract small list of chars from a bigger list of chars.
lets say I have:
let list_of_chars = ['#' ; 'a' ; 'b' ; 'c'; ... ; '!' ; '3' ; '4' ; '5' ];;
I have the following knowledge - I know that in the
list above I have '#' followed by a '!' in some location further in the list .
I want to extract the lists ['a' ;'b' ;'c' ; ...] and ['3' ; '4' ; '5'] and do something with them,
so I do the following thing:
let variable = match list_of_chars with
| '#'::l1#['!']#l2 -> (*[code to do something with l1 and l2]*)
| _ -> raise Exception ;;
This code doesn't work for me, it's throwing errors. Is there a simple way of doing this?
(specifically for using match)
As another answer points out, you can’t use pattern matching for this because pattern matching only lets you use constructors and # is not a constructor.
Here is how you might solve your problem
let split ~equal ~on list =
let rec go acc = function
| [] -> None
| x::xs -> if equal x on then Some (rev acc, xs) else go (x::acc) xs
in
go [] list
let variable = match list_of_chars with
| '#'::rest ->
match split rest ~on:'!' ~equal:(Char.equal) with
| None -> raise Exception
| Some (left,right) ->
... (* your code here *)
I’m now going to hypothesise that you are trying to do some kind of parsing or lexing. I recommend that you do not do it with a list of chars. Indeed I think there is almost never a reason to have a list of chars in ocaml: a string is better for a string (a chat list has an overhead of 23x in memory usage) and while one might use chars as a kind of mnemonic enum in C, ocaml has actual enums (aka variant types or sum types) so those should usually be used instead. I guess you might end up with a chat list if you are doing something with a trie.
If you are interested in parsing or lexing, you may want to look into:
Ocamllex and ocamlyacc
Sedlex
Angstrom or another parser generator like it
One of the regular expression libraries (eg Re, Re2, Pcre (note Re and Re2 are mostly unrelated)
Using strings and functions like lsplit2
# is an operator, not a valid pattern. Patterns need to be static and can't match a varying number of elements in the middle of a list. But since you know the position of ! it doesn't need to be dynamic. You can accomplish it just using :::
let variable = match list_of_chars with
| '#'::a::b::c::'!'::l2 -> let l1 = [a;b;c] in ...
| _ -> raise Exception ;;
I have the following list of sublists
[[1;5;10];
[2;6;11];
[3;7;12]];
I am trying to a create the following list of sublists:
[[1;2;3];
[5;6;7];
[10;11;12]]
The first sublist of the result should containt the first element of each original sublist, second result sublist should contian the second elements of each of the original sublists and so on.
Each sublist contains the same number of elements as the other sublists. The amount of sublists is at least 2.
I was thinking of using List.map but I am not sure what function to apply to each sublist to exctract the needed elements.
This is what I have so far:
let rec compute list =
List.map (fun x -> ) list
Any suggestions are appreciated!
Here you need two recursions (as you would need 2 imbricated loops in an imperative language).
The first recursion should allow you to go through the inputs line, say from 1 to 3, and at each step of this recursion, you will need a second recursion,to go along the full row.
You can either do it all by hand or you can use List.fold_left. (I would use fold for the inner recursion.
I wrote the following code to find the last element of a list in haskell:
myLast (x:xs) = do
ret <- if xs == [] then x else (myLast xs)
return ret
The idea is to traverse the list until we are at an element which has the empty list as its next element. When we find it we set ret to that element.
It makes sense for me but when I run the code inside the interactive shell I get the following error:
<interactive>:1:1: error:
• No instance for (Num (m0 b0)) arising from a use of ‘it’
• In a stmt of an interactive GHCi command: print it
edit 1
The reason I used do was because I saw that pattern being used somewhere to also traverse a list, so I thought I could do the same here. I'am avoiding libraries for now to get comfortable with the language.
I wrote the function avoiding the do keyword and now it works:
myLast(x:xs) = if xs == [] then x else (myLast xs)
There's now just an issue with the empty list case. How to approach this in haskell?
let's start with the signature of your function
myLast :: [a] -> a
now, for an empty list input, what can be expected as the output? How you can make up an instance of an arbitrary type a?
Alternatively, you can defer the handling of missing last element to the callers of your function.
myLast :: [a] -> Maybe a
You want
myLast (x:xs) =
to be equal to
if xs == [] then x else (myLast xs)
Great, xs == [], so let's just put it back in:
myLast (x:[]) = x
but what about the else part? Well, let's add another equation for that,
myLast (_:xs) = myLast xs
and we're golden.
What if we call it with an empty list [] though? No definition case will match, and we will get some kind of a run-time error. Well, same thing happens with the built-in function last too, so we're no better and no worse than Haskell itself here.
What is that match that I mentioned, you ask? That's how Haskell functions get invoked. Each function definition can have several clauses, starting with the function's name, and containing a pattern for each expected argument.
In a left hand side of an equation,
(x:[]) is a pattern, matching any singleton list. It can also be written [x]. x will refer to the list's only element, if used in the right-hand side of the equation.
[] is a pattern, matching any empty list.
(x:xs) is a pattern, matching any non-empty list. x will refer to the list's head (i.e. first) element, if used in the right-hand side of the equation; and xs will refer to the rest of the elements in a list (which are also, a list -- also known as its tail).
But wait, you ask. Wouldn't both clauses match for a singleton list, the first for the pattern [x] and the second for (_:xs) with xs matched up with an empty list, []?
Why yes, they both would match indeed; (x:[]) and (_:xs) are not mutually exclusive.
But that's OK, because in Haskell, if the first clause has matched, that's it -- that is the clause that gets executed, and no other attempts at any additional pattern matching and clause selection are made.
That would be Prolog, and that's quite another language.
// But pattern matching also makes it easy.
def penultimateRecursive[A](ls: List[A]): A = ls match {
case h :: _ :: Nil => h
case _ :: tail => penultimateRecursive(tail)
case _ => throw new NoSuchElementException
}
Can someone comment what this is doing line by line?
Is the [A] a generic like in c# we would do ?
h doesn't seem to be defined?
I think the major part of the algo is the recursive call:
case _ :: tail => penultimateRecursive(tail)
There doesnt' seem to be a check for 2 items in the list, and then taking the 1st item to get the 2nd last, confused!
The keys to understanding the pattern match are to realize that x :: y will only match a list with a single item x followed by the rest of the list y (which could be just Nil, or could be many elements), and that _ means "there needs to be something here, but we won't bother naming it". (And that the matches occur in order, and that lists end with Nil.)
You're correct that [A] is a generic type.
So, the first line:
case h :: _ :: Nil => h
says, if our list looks like (conceptually) Node(h) -> Node(whatever) -> Nil, then we return h. This is exactly a two-element list with the first item selected. Note that Nil does not match any arbitrary tail of the list; it matches only the end-of-list item Nil. This is because of a rule that Scala uses to distinguish the two: lower case variables are treated as wildcards that are to have the appropriate value filled in, while upper case variables are treated as constants to match. (If you must match a lower-case name, you can if surround it by backticks.)
Okay, now suppose it's not a two-element list. Then if it's not empty, it will match
case _ :: tail => penultimateRecursive(tail)
so if we haven't got a two-element list, we throw away the first item and try again. Finally, if we somehow never ended up with a two-element list, we get to
case _ => throw new NoSuchElementException
and we're done. (This could also be case Nil, actually, since this is the only possibility that doesn't match the other two entries.)
A is a type variable, meaning the function is defined generically for any type A.
h is bound by the pattern matching: the first case states, if there are exactly two elements, then call the first h and return it.
There doesnt' seem to be a check for 2 items in the list
There is: h :: _ :: Nil means "an element h, followed by any element, followed by no more elements." Nil isn't an element, it's the end of the list.
and then taking the 1st item to get the 2nd last
Taking the first of a two-element list means taking the penultimate. If the list has fewer or more elements than two, the other two cases apply.
larsmans and Rex have covered your questions, but see Chapter 9 for more details on '::' http://www.scala-lang.org/docu/files/ScalaByExample.pdf
The first line means that any list element h will be returned if h is followed by another one and a Nil pointer (at the end of the list). The actual element following to h is not important, that's why you use _ to specify that there is an element but you don't care about its value.
If the first case does not match, the second case will invoke recursion if the list has a head element and a tail of at least one element.
Lastly you bail out on lists consisting only a single element. Once again, you don't have to care about the actual value of the elements value.
New to Haskell and have a stumbling block. I'm trying to filter a list of tuples based on the first item.
filter (==(x,_)) lis
I get an illegal '_' error, but I'm not sure how I can get around it?
In Haskell, you cannot iterate over a tuple like you can a list.
If the tuple only has two items, you can use fst to retrieve the first item of the tuple and snd to retrieve the second item.
One way to do what I think you want to do is this approach:
Prelude> let lst = [(1,2), (3,4)]
Prelude> filter ((==1).fst) lst
[(1,2)]
Which only returns the items in the list where the first element is equal to 1; of course, you can substitute x where I put 1.
To be a little more specific, (==1).fst first applies fst to the element in lst, then applies (==1) to the result of fst -- technically, the dot composes the two functions together.
You can't give an argument with a wildcard _ in it to the == operator (or to any other function). The argument needs to be a real value, not a pattern that should be matched against.
If you want to use pattern matching you could use a lambda function as you filter condition:
filter (\(a,_) -> a == x) lis
Also, there is the predefined function fst to extract the first element of a two-element tuple. This can be combined with == to do the same test:
filter ((== x) . fst)) lis