Haskell accesing the sublist while filtering a list of a list - haskell

I'm fairly new to Haskell, and try to accomplish the following:
filter (((!!) subList (fromJust (elemIndex String [String]))) == String) [[string]]
I replaced the names with their types to make it easier to read. The problem is that i can't do subList, but the (!!) takes a list as argument. So how would i go about writing this?
edit:
I wrote the filtering condition seperately, which works, but the problem is still the same:
findGood :: [String] -> String -> [String] -> String -> Bool
but i still need to fill in all the values, though the first [String] is the sublist. All the other values can be entered..
Edit:
I solved it, what i needed to do was put the [String] last, and then i could leave it out in the filter
So
findGood :: String -> [String] -> String -> [String] -> Bool
filter (findGood a b c) [[String]]
Thats what works, and thats what I wanted. (not needing the D)

Given that you're wanting to compare money and check money > 500 it makes much more sense to store it as an Int not a String. Furthermore I would say storing each entry as a tuple and having a list of tuples makes more sense than using a list of lists (this is also required for the Int implementation of money as you can't have a list of different types of lists).
So the table would have type [(String, Int)].
filter goes through the list and checks each element against a condition. In this case the condition is so simple I wouldn't bother making it it's own function (unless you need to reuse it in lots of places).
When given a pair of type (String, Int) we just want to check if that second value is > 500. So the condition is simply snd row > 500 where row is the tuple we were given representing a row in the table.
This leaves us with:
filter (\row -> snd row > 500) table
Testing on [("Geoff", 600), ("Bill", 700), ("Bill Jr.", 10)] this gives [("Geoff", 600), ("Bill", 700)] as expected.

Related

Using Filter that requires multiple Input - Haskell

I'm relatively new to Haskell, and have been trying to learn it for the past few weeks, but have been stuck on Filters and Predicates, which I was hoping to get help with understanding.
I have come across a problem whereby I have a list of tuples. Each tuple consists of a (songName, songArtist, saleQty) and am required to remove a tuple from that list based on the user inputting the songName and SongArtist.
When returning the results, I understand I can remove a tuple by using the Filter function when returning the results. I have been doing some reading on it using LYAH. Its taught me that I have to use a Predicate (which is another function) to filter through my results. This has caught me off guard as I learnt a Filter function has type (a -> Bool) -> [a] -> [a], which means my input for the Filter needs to to be a Boolean and my output for my Predicate needs to be Boolean so it can be fed to the Filter.
This is a problem, as to filter my results from the list I need to input the songName and songArtist (both of which are String types) to the predicate when recursively going through the results, and output the songName and songArtist to the Filter to let it know which exact tuple needs to be removed from the list.
Am I going about this the wrong way or is there a better way I could go about this?
I learnt a Filter function has type (a -> Bool) -> [a] -> [a]
The filter :: (a -> Bool) -> [a] -> [a] takes two parameters, a predicate with signature a -> Bool, and a list of items, and it returns a list of items that satisfy the predicate. So the predicate is the first parameter.
which means my input for the Filter needs to to be a Boolean.
No the first parameter has type a -> Bool, so it is a function that maps an item a to a Bool, so a predicate.
You can for example create a function that checks if both the songName and songTitle match with:
filterSales :: String -> String -> [(String, String, Int)] -> [(String, String, Int)]
filterSales artist title items = filter p items
where p (artist', title', _) = artist == artist' && title == title'
Here p is thus the predicate, a function that maps a 3-tuple to a boolean. The predicate p will return True for a 3-tuple if the first two items are equal to the artist and title respectively.
This is a second answer and the existing one is great, so I'll show my alternate take; after all, two explanations can't be worse than one, right?
What filter expects of you is a function that will tell it one thing - should I keep the given element in the resulting collection?
The type of that function is (a -> Bool), and that's what we call a predicate.
In your specific case, assuming
type SongEntry = (SongName, SongArtist, SaleQty)
It's gonna be a function of type SongEntry -> Bool. Now, there could be a lot of such functions... maybe you want more than 100 sales?
hasMoreThan100Sales :: SongEntry -> Bool
hasMoreThan100Sales (_, _, sales) = sales > 100
To use it:
filter hasMoreThan100Sales songs
That should be easy enough. What if we wanted more than n sales? This is where Haskell's curry-by-default really shines. We can add one additional parameter:
hasMoreThanNSales :: Int -> SongEntry -> Bool
Which we can also read and understand as Int -> (SongEntry -> Bool). The implementation is straighforward at this point:
hasMoreThanNSales n (_, _, sales) = sales > n
And crucially, to get our previous "100" function, we just need to apply it:
hasMoreThanNSales 100 :: SongEntry -> Bool
This has the type we need to use it with the filter:
filter (hasMoreThanNSales 100) songs
At this point, you should understand it well enough to write your own predicate that can be parametrized in any way you want.
Oh, and one more thing that might be confusing. hasMoreThan100Sales is a predicate. hasMoreThanNSales is not, until you apply it with a value (e.g. 100) - (hasMoreThanNSales 100) is a predicate.

Haskell taking in two list with a int and returning a tuple

I am trying to learn haskell and saw a exercise which says
Write two different Haskell functions having the same type:
[a] -> [b] -> Int -> (a,b)
So from my understanding the expressions should take in two lists, an int and return a tuple of the type of the lists.
What i tried so far was
together :: [a] -> [b] -> Int -> (a,b)
together [] [] 0 = (0,0)
together [b] [a] x = if x == a | b then (b,a) else (0,0)
I know I am way off but any help is appreciated!
First you need to make your mind up what the function should return. That is partly determined by the signature. But still you can come up with a lot of functions that return different things, but have the same signature.
Here one of the most straightforward functions is probably to return the elements that are placed on the index determined by the third parameter.
It makes no sense to return (0,0), since a and b are not per se numerical types. Furthermore if x == a | b is not semantically valid. You can write this as x == a || x == b, but this will not work, since a and b are not per se Ints.
We can implement a function that returns the heads of the two lists in case the index is 0. In case the index is negative, or at least one of the two lists is exhausted, then we can raise an error. I leave it as an exercise what to do in case the index is greater than 0:
together :: [a] -> [b] -> Int -> (a,b)
together [] _ = error "List exhausted"
together _ [] = error "List exhausted"
together (a:_) (b:_) 0 = (a, b)
together (a:_) (b:_) n | n < 0 = error "Negative index!"
| …
you thus still need to fill in the ….
I generally dislike those "write any function with this signature"-type excercises precisely because of how arbitrary they are. You're supposed to figure out a definition that would make sense for that particular signature and implement it. In a lot of cases, you can wing it by ignoring as many arguments as possible:
fa :: [a] -> [b] -> Int -> (a,b)
fa (a:_) (b:_) _ = (a,b)
fa _ _ _ = error "Unfortunately, this function can't be made total because lists can be empty"
The error here is the important bit to note. You attempted to go around that problem by returning 0s, but this will only work when 0 is a valid value for types of a and b. Your next idea could be some sort of a "Default" value, but not every type has such a concept. The key observation is that without any knowledge about a type, in order to produce a value from a function, you need to get this value from somewhere else first*.
If you actually wanted a more sensible definition, you'd need to think up a use for that Int parameter; maybe it's the nth element from each
list? With the help of take :: Int -> [a] -> [a] and head :: [a] -> a this should be doable as an excercise.
Again, your idea of comparing x with a won't work for all types; not every type is comparable with an Int. You might think that this would make generic functions awfully limited; that's the point where you typically learn about how to express certain expectations about the types you get, which will allow you to operate only on certain subsets of all possible types.
* That's also the reason why id :: a -> a has only one possible implementation.
Write two different Haskell functions having the same type:
[a] -> [b] -> Int -> (a,b)
As Willem and Bartek have pointed out, there's a lot of gibberish functions that have this type.
Bartek took the approach of picking two based on what the simplest functions with that type could look like. One was a function that did nothing but throw an error. And one was picking the first element of each list, hoping they were not empty and failing otherwise. This is a somewhat theoretical approach, since you probably don't ever want to use those functions in practice.
Willem took the approach of suggesting an actually useful function with that type and proceeded to explore how to exhaust the possible patterns of such a function: For lists, match the empty list [] and the non-empty list a:_, and for integers, match some stopping point, 0 and some categories n < 0 and ….
A question that arises to me is if there is any other equally useful function with this type signature, or if a second function would necessarily have to be hypothetically constructed. It would seem natural that the Int argument has some relation to the positions of elements in [a] and [b], since they are also integers, especially because a pair of single (a,b) is returned.
But the only remotely useful functions (in the sense of not being completely silly) that I can think of are small variations of this: For example, the Int could be the position from the end rather than from the beginning, or if there's not enough elements in one of the lists, it could default to the last element of a list rather than an error. Neither of these are very pleasing to make ("from the end" conflicts with the list being potentially infinite, and having a fall-back to the last element of a list conflicts with the fact that lists don't necessarily have a last element), so it is tempting to go with Bartek's approach of writing the simplest useless function as the second one.

Get elements with odd length in a Haskell list of strings

I have a list of strings in Haskell and I need to get those elements with odd length in another list. How can this be done using higher order functions like foldr, foldl, foldr1, foldl1, filter, map, and so on? I will very much appreciate your help. Can list comprehension be used in this case?
It seems that you are aware that filter exists (since you've mentioned), but perhaps are uncertain how it works. If you're trying to extract a specific subset of a list, this seems to be the right path. If you look at its type-signature, you'll find it's pretty straight-forward:
(a -> Bool) -> [a] -> [a]
That is, it takes a function that returns True or False (i.e. true to contain in the new set, false otherwise) and produces a new list. Similarly, Haskell provides a function called odd in Prelude. It's signature looks as follows:
Integral a => a -> Bool
That is, it can take any Integral type and returns True if it is odd, false otherwise.
Now, let's consider a solution:
filter odd [1..10]
This will extract all the odd numbers between [1,10].
I noticed you mentioned list comprehensions. You probably do not want to use this if you are already given a list and you are simply filtering it. However, a list comprehension would be a perfectly acceptable solution:
[x | x <- [1..10], odd x]
In general, list comprehensions are used to express the generation of lists with more complicated constraints.
Now, to actually answer your question. Since we know we can filter numbers, and if we're using Hoogle searching for the following type (notice that String is simply [Char]):
[a] -> Int
You will see a length function. With some function composition, we can quickly see how to create a function which filters odd length. In summary, we have odd which is type Int -> Bool (in this case) and we have length which is [a] -> Int or-- specifically-- String -> Int. Our solution now looks like this:
filter (odd . length) ["abc","def","eh","123","hm","even"]
Here ya go.
getOddOnes = filter . flip (foldr (const (. not)) id) $ False
Note: if you turn this in for your homework, you'd best be prepared to explain it!

Searching through tuple of more than 2 elements

How can I search a tuple based on the first element or second or third?
I know how to search tuple of two but how do i do it for more than two?
type Stuff = (String, String, Int)
testStuff :: [Stuff]
testStuff = [
("beans","black",5),
("cod","fish",4),
("coke","diet",3)
]
How can I write a function that will search "Stuff" and return the "int" value?
e.g searchStuff "beans" should return 5.
Since you haven't provided your function for searching in a list of pairs, I'm going to assume that you used lookup. Lets focus on find for your new function. find can be found in Data.List (and a more general version in Data.Foldable) and has the following type:
find :: (a -> Bool) -> [a] -> Maybe a
Now, if you need to find something in a list of triples based on the first element, you could use
find (\(a,_,_) -> a == "beans") testStuff
However, this will leave you with a Maybe Stuff. But since Maybe is an instance of Functor, it is easy to change the result to Maybe Int (and is left as an exercise).
The Prelude defines lookup to handle searching a list of pairs. Here's the definition:
-- | 'lookup' #key assocs# looks up a key in an association list.
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup _key [] = Nothing
lookup key ((x,y):xys)
| key == x = Just y
| otherwise = lookup key xys
Can you see how one would define a similar function to search a list of triples?

Searching in List of Tuples

I have a list of tuples stored in a text file.
[(1,"123","Shiva","address #1",77000),(2,"123","Sina","address #2", 1900)]
The first element of each tuple is acount_Id and the second element of each tuple is password and in the application I tend to read the list from the file and ask for account no and password from the user and look for it in the file. I tried this:
x <- readFile "database.txt"
y <- tuples x
let account = [(a,b)|(a,b,c,d,e) <- y, ac_no ==a , pass == b]
tuples is a function that takes a string and give output of IO [(AccNo, Pass, Name, Address, Balance)] data type
Any idea how can I improve this process by using higher order function instead of list processing?
Thanks in advance!
There is a function lookup which has the type signature:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
But this is only defined for pairs.
One option would be to use types to specialize to get this arrangement.
data UserDetails = UserDetails {
password :: String
address :: String
}
And define your list as (String,UserDetails) pairs, then you'd be able to use the lookup function. Putting your data into types (rather than just lots of strings) is in general a really good thing to do anyway, so I think this would be good.
If you did want to use a higher-order function, take a look at find, which will return the first of a list matching a pattern.
Something like
type UserDataAssociation = (String,String,String,String,String)
findMatchingAssociations :: [UserDataAssociation] -> String -> Maybe UserDataAssociation
findMatchingAssociations xs password = find (\(pw,a) -> pw == password) xs

Resources