Searching through tuple of more than 2 elements - haskell

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?

Related

How to use maybe in a list in Haskell?

I am using haskell and the following:
convertToBasis :: [String] -> Maybe [Basis]
convertToBasis [] = Nothing
convertToBasis (h:t) = basis : convertToBasis t
where
basis = toCandidateBasis h
Returns a type of [Maybe Basis] I want a type of Maybe [Basis]
toCandidateBasis is shown below:
toCandidateBasis :: String -> Maybe Basis
toCandidateBasis myStr = if not $ has7UniqueLetters myStr [] then
Nothing
else
Just (dedupAndSort myStr)
The function returns nothing if a String does not have 7 unique characters otherwise it removes duplicates and sorts the String alphabetically and return that result. Now the return type of the function is Maybe Basis. Hence when I when I get a list of strings and want to convert them to their respective candidate basises one by one, it will concat all the maybes and return me a type of:
[Maybe Basis]
But I want a type of
Maybe [Basis]
It should return Nothing only when the given Basis array is empty otherwise return some result. How do I do this?
There's really no reason to use a Maybe [a] unless there is a semantic difference between Nothing and Just [], which it sounds like there is not in your case. However, it is a fairly common use case to reduce a list [Maybe a] to a list [a] by removing all the Nothings— so common, in fact, that there's a builtin function for doing that: catMaybes :: [Maybe a] -> [a].

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.

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

Creating a list type using functions

For a silly challenge I am trying to implement a list type using as little of the prelude as possible and without using any custom types (the data keyword).
I can construct an modify a list using tuples like so:
import Prelude (Int(..), Num(..), Eq(..))
cons x = (x, ())
prepend x xs = (x, xs)
head (x, _) = x
tail (_, x) = x
at xs n = if n == 0 then xs else at (tail xs) (n-1)
I cannot think of how to write an at (!!) function. Is this even possible in a static language?
If it is possible could you try to nudge me in the right direction without telling me the answer.
There is a standard trick known as Church encoding that makes this easy. Here's a generic example to get you started:
data Foo = A Int Bool | B String
fooValue1 = A 3 False
fooValue2 = B "hello!"
Now, a function that wants to use this piece of data must know what to do with each of the constructors. So, assuming it wants to produce some result of type r, it must at the very least have two functions, one of type Int -> Bool -> r (to handle the A constructor), and the other of type String -> r (to handle the B constructor). In fact, we could write the type that way instead:
type Foo r = (Int -> Bool -> r) -> (String -> r) -> r
You should read the type Foo r here as saying "a function that consumes a Foo and produces an r". The type itself "stores" a Foo inside a closure -- so that it will effectively apply one or the other of its arguments to the value it closed over. Using this idea, we can rewrite fooValue1 and fooValue2:
fooValue1 = \consumeA consumeB -> consumeA 3 False
fooValue2 = \consumeA consumeB -> consumeB "hello!"
Now, let's try applying this trick to real lists (though not using Haskell's fancy syntax sugar).
data List a = Nil | Cons a (List a)
Following the same format as before, consuming a list like this involves either giving a value of type r (in case the constructor was Nil) or telling what to do with an a and another List a, so. At first, this seems problematic, since:
type List a r = (r) -> (a -> List a -> r) -> r
isn't really a good type (it's recursive!). But we can instead demand that we first reduce all the recursive arguments to r first... then we can adjust this type to make something more reasonable.
type List a r = (r) -> (a -> r -> r) -> r
(Again, we should read the type List a r as being "a thing that consumes a list of as and produces an r".)
There's one final trick that's necessary. What we would like to do is to enforce the requirement that the r that our List a r returns is actually constructed from the arguments we pass. That's a little abstract, so let's give an example of a bad value that happens to have type List a r, but which we'd like to rule out.
badList = \consumeNil consumeCons -> False
Now, badList has type List a Bool, but it's not really a function that consumes a list and produces a Bool, since in some sense there's no list being consumed. We can rule this out by demanding that the type work for any r, no matter what the user wants r to be:
type List a = forall r. (r) -> (a -> r -> r) -> r
This enforces the idea that the only way to get an r that gets us off the ground is to use the (user-supplied) consumeNil function. Can you see how to make this same refinement for our original Foo type?
If it is possible could you try and nudge me in the right direction without telling me the answer.
It's possible, in more than one way. But your main problem here is that you've not implemented lists. You've implemented fixed-size vectors whose length is encoded in the type.
Compare the types from adding an element to the head of a list vs. your implementation:
(:) :: a -> [a] -> [a]
prepend :: a -> b -> (a, b)
To construct an equivalent of the built-in list type, you'd need a function like prepend with a type resembling a -> b -> b. And if you want your lists to be parameterized by element type in a straightforward way, you need the type to further resemble a -> f a -> f a.
Is this even possible in a static language?
You're also on to something here, in that the encoding you're using works fine in something like Scheme. Languages with "dynamic" systems can be regarded as having a single static type with implicit conversions and metadata attached, which obviously solves the type mismatch problem in a very extreme way!
I cannot think of how to write an at (!!) function.
Recalling that your "lists" actually encode their length in their type, it should be easy to see why it's difficult to write functions that do anything other than increment/decrement the length. You can actually do this, but it requires elaborate encoding and more advanced type system features. A hint in this direction is that you'll need to use type-level numbers as well. You'd probably enjoy doing this as an exercise as well, but it's much more advanced than encoding lists.
Solution A - nested tuples:
Your lists are really nested tuples - for example, they can hold items of different types, and their type reveals their length.
It is possible to write indexing-like function for nested tuples, but it is ugly, and it won't correspond to Prelude's lists. Something like this:
class List a b where ...
instance List () b where ...
instance List a b => List (b,a) b where ...
Solution B - use data
I recommend using data construct. Tuples are internally something like this:
data (,) a b = Pair a b
so you aren't avoiding data. The division between "custom types" and "primitive types" is rather artificial in Haskell, as opposed to C.
Solution C - use newtype:
If you are fine with newtype but not data:
newtype List a = List (Maybe (a, List a))
Solution D - rank-2-types:
Use rank-2-types:
type List a = forall b. b -> (a -> b -> b) -> b
list :: List Int
list = \n c -> c 1 (c 2 n) -- [1,2]
and write functions for them. I think this is closest to your goal. Google for "Church encoding" if you need more hints.
Let's set aside at, and just think about your first four functions for the moment. You haven't given them type signatures, so let's look at those; they'll make things much clearer. The types are
cons :: a -> (a, ())
prepend :: a -> b -> (a, b)
head :: (a, b) -> a
tail :: (a, b) -> b
Hmmm. Compare these to the types of the corresponding Prelude functions1:
return :: a -> [a]
(:) :: a -> [a] -> [a]
head :: [a] -> a
tail :: [a] -> [a]
The big difference is that, in your code, there's nothing that corresponds to the list type, []. What would such a type be? Well, let's compare, function by function.
cons/return: here, (a,()) corresponds to [a]
prepend/(:): here, both b and (a,b) correspond to [a]
head: here, (a,b) corresponds to [a]
tail: here, (a,b) corresponds to [a]
It's clear, then, that what you're trying to say is that a list is a pair. And prepend indicates that you then expect the tail of the list to be another list. So what would that make the list type? You'd want to write type List a = (a,List a) (although this would leave out (), your empty list, but I'll get to that later), but you can't do this—type synonyms can't be recursive. After all, think about what the type of at/!! would be. In the prelude, you have (!!) :: [a] -> Int -> a. Here, you might try at :: (a,b) -> Int -> a, but this won't work; you have no way to convert a b into an a. So you really ought to have at :: (a,(a,b)) -> Int -> a, but of course this won't work either. You'll never be able to work with the structure of the list (neatly), because you'd need an infinite type. Now, you might argue that your type does stop, because () will finish a list. But then you run into a related problem: now, a length-zero list has type (), a length-one list has type (a,()), a length-two list has type (a,(a,())), etc. This is the problem: there is no single "list type" in your implementation, and so at can't have a well-typed first parameter.
You have hit on something, though; consider the definition of lists:
data List a = []
| a : [a]
Here, [] :: [a], and (:) :: a -> [a] -> [a]. In other words, a list is isomorphic to something which is either a singleton value, or a pair of a value and a list:
newtype List' a = List' (Either () (a,List' a))
You were trying to use the same trick without creating a type, but it's this creation of a new type which allows you to get the recursion. And it's exactly your missing recursion which allows lists to have a single type.
1: On a related note, cons should be called something like singleton, and prepend should be cons, but that's not important right now.
You can implement the datatype List a as a pair (f, n) where f :: Nat -> a and n :: Nat, where n is the length of the list:
type List a = (Int -> a, Int)
Implementing the empty list, the list operations cons, head, tail, and null, and a function convert :: List a -> [a] is left as an easy exercise.
(Disclaimer: stole this from Bird's Introduction to Functional Programming in Haskell.)
Of course, you could represent tuples via functions as well. And then True and False and the natural numbers ...

What to call a function that splits lists?

I want to write a function that splits lists into sublists according to what items satisfy a given property p. My question is what to call the function. I'll give examples in Haskell, but the same problem would come up in F# or ML.
split :: (a -> Bool) -> [a] -> [[a]] --- split lists into list of sublists
The sublists, concatenated, are the original list:
concat (split p xss) == xs
Every sublist satisfies the initial_p_only p property, which is to say (A) the sublist begins with an element satisfying p—and is therefore not empty, and (B) no other elements satisfy p:
initial_p_only :: (a -> Bool) -> [a] -> Bool
initial_p_only p [] = False
initial_p_only p (x:xs) = p x && all (not . p) xs
So to be precise about it,
all (initial_p_only p) (split p xss)
If the very first element in the original list does not satisfy p, split fails.
This function needs to be called something other than split. What should I call it??
I believe the function you're describing is breakBefore from the list-grouping package.
Data.List.Grouping: http://hackage.haskell.org/packages/archive/list-grouping/0.1.1/doc/html/Data-List-Grouping.html
ghci> breakBefore even [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6]
[[3,1],[4,1,5,9],[2],[6,5,3,5],[8,9,7,9,3],[2,3],[8],[4],[6],[2],[6]]
I quite like some name based on the term "break" as adamse suggests. There are quite a few possible variants of the function. Here is what I'd expect (based on the naming used in F# libraries).
A function named just breakBefore would take an element before which it should break:
breakBefore :: Eq a => a -> [a] -> [[a]]
A function with the With suffix would take some kind of function that directly specifies when to break. In case of brekaing this is the function a -> Bool that you wanted:
breakBeforeWith :: (a -> Bool) -> [a] -> [[a]]
You could also imagine a function with By suffix would take a key selector and break when the key changes (which is a bit like group by, but you can have multiple groups with the same key):
breakBeforeBy :: Eq k => (a -> k) -> [a] -> [[a]]
I admit that the names are getting a bit long - and maybe the only function that is really useful is the one you wanted. However, F# libraries seem to be using this pattern quite consistently (e.g. there is sort, sortBy taking key selector and sortWith taking comparer function).
Perhaps it is possible to have these three variants for more of the list processing functions (and it's quite good idea to have some consistent naming pattern for these three types).

Resources