Gaining an Element from a List of Tuples in Haskell - list

So I have a list of tuples defined like so:
type Domino = (Int,Int)
data End = L|R
type Board = [Domino]
d :: Domino
d= (4,5)
b :: Board
b= [(1,3),(3,3),(3,4)]
In my function I need to be able to gain the first part of the board. So for example I can head the board to get the domino (1,3) as a tuple but I've been trying to get the integer one from this and simply failing. I need to be able to compare that integer value. My question is simply how do you acquire the first part of a tuple in an a list as everything I have done and searched keeps failing. Apologies if this is really simple, I am new to haskell. This is my function code, obviously with a bunch of errors
goesP :: Domino->Board->End-> Bool
goesP _ []_ = True
goesP dom bor L = (if head bor fst == fst dom then True else if last bor == snd then True else False)

Something as simple as
goesP :: Domino -> Board -> End -> Bool
goesP _ [] _ = True
goesP _ ((a,b):doms) _ = a
will work, as you can pattern match for the list being empty, and then being a pair cons the rest of a list, and extract the first element out of that pair.
I'm not sure what you're trying to do with the End type in there as well, but I left it in there in my example (although I do nothing with it).

From your question, it doesn't look like you're interested in a generalised function, so these will work:
fst $ head b will get the very first Int in that list, and snd $ last b will get the very last.
How you compare them then is up to you.

As you may or may not know fst and snd only work for 2-element tuples so for you it should be enough:
fst (a,b) = a
You can also write you own:
get3th (_,_,a,_,_,_,_,_,_,_) = a
As you can see you may want to define your own type.

Related

how to add a number in a 2D list with specific index in haskell

I'm beginner in haskell and I tried to add a number in a 2D list with specific index in haskell but I don't know how to do
example i have this:
[[],[],[]]
and I would like to put a number (3) in the index 1 like this
[[],[3],[]]
I tried this
[array !! 1] ++ [[3]]
but it doesn't work
As you may have noticed in your foray so far, Haskell isn't like many other languages in that it is generally immutable, so trying to change a value, especially in a deeply nested structure like that, isn't the easiest thing. [array !! 1] would give you a nested list [[]] but this is not mutable, so any manipulations you do this structure won't be reflected in the original array, it'll be a separate copy.
(There are specialized environments where you can do local mutability, as with e.g. Vectors in the ST monad, but these are an exception.)
For what you're trying to do, you'll have to deconstruct the list to get it to a point where you can easily make the modification, then reconstruct the final structure from the (modified) parts.
The splitAt function looks like it will help you with this: it takes a list and separates it into two parts at the index you give it.
let array = [[],[],[]]
splitAt 1 array
will give you
([[]], [[],[]])
This helps you by getting you closer to the list you want, the middle nested list.
Let's do a destructuring bind to be able to reconstruct your final list later:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
Next, you'll need to get at the sub-list you want, which is the first item in the end list:
desired = head end
Now you can make your modification -- note, this will produce a new list, it won't modify the one that's there:
desired' = 3:desired
Now we need to put this back into the end list. Unfortunately, the end list is still the original value of [[],[]], so we'll have to replace the head of this with our desired' to make it right:
end' = desired' : (tail end)
This drops the empty sub-list at the beginning and affixes the modified list in its place.
Now all that's left is to recombine the modified end' with the original beginning:
in beginning ++ end'
making the whole snippet:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
desired = head end
desired' = 3:desired
end' = desired' : (tail end)
in beginning ++ end'
or, if you're entering all these as commands in the REPL:
let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'
As paul mentions, things in Haskell are immutable. What you want to do must be done not be modifying the list in place, but by destructuring the list, transforming one of its parts, and restructuring the list with this changed part. One way of destructuring (via splitAt) is put forth there; I'd like to offer another.
Lists in Haskell are defined as follows:
data [] a = [] | a : [a]
This reads "A list of a is either empty or an a followed by a list of a". (:) is pronounced "cons" for "constructor", and with it, you can create nonempty lists.
1 : [] -> [1]
1 : [2,3] -> [1,2,3]
1 : 2 : 3 : [] -> [1,2,3]
This goes both ways, thanks to pattern matching. If you have a list [1,2,3], matching it to x : xs will bind its head 1 to the name x and its tail [2,3] to xs. As you can see, we've destructured the list into the two pieces that were initially used to create it. We can then operate on those pieces before putting the list back together:
λ> let x : xs = [1,2,3]
λ> let y = x - 5
λ> y : xs
[-4,2,3]
So in your case, we can match the initial list to x : y : z : [], compute w = y ++ [3], and construct our new list:
λ> let x : y : z : [] = [[],[],[]]
λ> let w = y ++ [3]
λ> [x,w,z]
[[],[3],[]]
But that's not very extensible, and it doesn't solve the problem you pose ("with specific index"). What if later on we want to change the thousandth item of a list? I'm not too keen on matching that many pieces. Fortunately, we know a little something about lists—index n in list xs is index n+1 in list x:xs. So we can recurse, moving one step along the list and decrementing our index each step of the way:
foo :: Int -> [[Int]] -> [[Int]]
foo 0 (x:xs) = TODO -- Index 0 is x. We have arrived; here, we concatenate with [3] before restructuring the list.
foo n (x:xs) = x : foo (n-1) xs
foo n [] = TODO -- Up to you how you would like to handle invalid indices. Consider the function error.
Implement the first of those three yourself, assuming you're operating on index zero. Make sure you understand the recursive call in the second. Then read on.
Now, this works. It's not all that useful, though—it performs a predetermined computation on a specified item in a list of one particular type. It's time to generalize. What we want is a function of the following type signature:
bar :: (a -> a) -> Int -> [a] -> [a]
where bar f n xs applies the transformation f to the value at index n in the list xs. With this, we can implement the function from before:
foo n xs = bar (++[3]) n xs
foo = bar (++[3]) -- Alternatively, with partial application
And believe it or not, changing the foo you already wrote into the much more useful bar is a very simple task. Give it a try!

head function for empty list issue

I want to use 'head' function inside map.
The problem is the 'head' function only accepts non-empty list.
I have list of list:
let ll =[["dog", "cat"], ["pig", "cow"], []]
I need to iterate the list of list twice
let listOne = filter(\x -> if length x > 0) ll
map(\x -> head x) listOne
I'm wondering whether I can iterate the list of list once or put a "if condition" inside the map without the 'filter'
Any suggestion would be appreciated.
Yes, in fact you can write it as a list comprehension statement, and use pattern matching instead:
result = [ h | (h:_) <- ll ]
or as a function:
heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]
So here we use the pattern (h:_) which matches all non-empty lists, and we directly obtain the head h of such list and add it to the list. If you use a pattern in list comprehension (on the left side of the left arrow <-, it will skip the elements that do not match the pattern).
This is also more safe than using length, since length will get stuck into an infinite loop if you are working with infinite lists. Furthermore by using patterns over the non-total head function, we have more syntactical guarantees that this function will work (yes, once the non-empty elements are filtered, we are of course certain that head will not result in errors, but we only know this because we have information about the head function).
Note that your attempt will result in a syntax error, since you use an if, without a then and else part.
Alternatively, we can, like #DanielWagner says, write the heads function differently, for instance using:
heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll
or by using the bind of the list monad:
heads :: [[a]] -> [a]
heads = (take 1 =<<)
or we can transpose the 2d list. In that case the first row contains all the heads of the lists. Since it is however not guaranteed that there is such a row, we can append an empty list at the end, like:
heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose

Haskell and manipulating a list of tuples

Ok so have been faced with a problem where basically I have a been told to make a multiset, or a list of tuples. (Char,Int) and then I have to write a function that takes a item and inserts it into this list, but if there is already a matching tuple in the list it increases the Int.
i.e. i had a list [(p,2),(w,3)] and i get another w it should give [(p,2),(w,4)]
How would you go about it, i've tried
listAdd :: Char->Int->ListOfT -> ListOfT
listAdd c i l
|length l == 0 =(c,i):l
|fst l == c = (c,i+1):l
but this gives loads of errors, i need to remove the list element at that point and replace it with with (c,i+1), so how do i remove from the list and how to i get i+1? also how do you make a loop which will go through all the elements in a list?
And i can't use any of the import Data stuff
I know this is asking a ton but any help would be great thanks.
Neo
Okay can this code be fiddled with so it can be used tto make tuples of any items not just chars. so i could load it up and make a list of tuples with stirngs instead, close it then load it up again and make a list of tuples of ints?
ok I think your idea is not bad you just have to get the details straight.
The loop you asked about is usually either done with recursion (as a list is a recursive structure that's a great idea) or with some higher order functions like map, filter, foldr, ... that will hide the recursion from you (you could say they abstract away the repeating stuff) - anway in this case I think the easiest way is just to go with what you started and use the direct recursion.
Here is a simple version (you maybe want to extent) that does the basic stuff:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c ((c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = (c',i) : listAdd c xs
as you can see the first case is very similar to what you had: if the dictionary (the second argument) is the empty list than you just add a new tuple with the char to insert and the number 1
if not then you check if the first element in the dictionary has the same character (c' here), if yes then you increase the count and if not you let this element stand as it is and recursively search through the rest of the dictionary.
Also note that you can use pattern matching here to not only deconstruct the dictionary into head::tail form but also deconstruct the head into (..,..) tuple parts as well.
If you want you can use a # in there to and get the second case a bit more concise:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c (x#(c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = x : listAdd c xs
PS: in case you wondered why I did not use your Int argument? Because I don't know what you want to do with it if there is already a value - here is a version where I just add it to it (seems resonable):
listAdd :: Char -> Int -> [(Char,Int)] -> [(Char,Int)]
listAdd c i [] = [(c,i)]
listAdd c i (x#(c',i'):xs)
| c' == c = (c,i+i'):xs
| otherwise = x : listAdd c i xs
List manipulations with just recursive functions can be indeed hard for beginners to grok, but in this case they should fit the problem nicely.
Let's start with a bit better signature and a helper.
type MyList = [(Char, Int)]
listAdd :: Char -> MyList -> MyList
listAdd p l = listAdd' p [] l
Notice that I've changed the signature to accept just Char; we don't need to supply the initial count, since if there are no such elements currently on the list, we'll just set it to 1 when adding a new element.
Okay, that's the basic skeleton. The helper is there just to make it easier to store the "already processed" part of the list. Let's look at it:
listAdd' :: Char -> MyList -> MyList -> MyList
First, we add the recursion end condition:
listAdd' p left [] = left ++ [(p, 1)]
This means that if we haven't found the element to replace earlier, we can just add it at the end.
listAdd' p left (x:right) = if p == fst x
then left ++ [(fst x, snd x + 1)] ++ right
else listAdd' p (left ++ [x]) right
Okay, so now we split up the "right" part to the first element of it and the rest. Let's look at the if:
if we managed to find the element, we can end the computation by appending the rest of the list to the modified element and what we had previously
if it's still not it, we proceed with recursion.
As an additional remark at the end, you could easily change Char to Eq a => a to allow your function to work on any type that can be directly compared, Char included.

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.

Pattern Matching and List Comprehension in List of Tuples

type a = [(Int,Int,Int,Int)]
fun:: a -> Int
func [a,b,c,d] = ?
I have a list of tuples like this what i required is to apply list comprehensions or pattern matching .. example taking sum or filter only divide 2 numbers ... i just want a start how to access values and or a list comprehension to this List of Tuples
To sum up the as, use something like this:
type A = [(Int, Int, Int, Int)]
func :: A -> Int
func tuples = sum [a | (a, b, c, d) <- tuples]
Also note that a type alias must begin with an upper case letter. Lower case letters are used for type variables.
hammar's answer covered list comprehensions, the basic schema for recursive functions using pattern matching is:
f [] = ..
f ((a,b,c,d):xs) = ..
So you need to specify a base case for a list containing no 4-tuples, and a recursive case for when the list consists of a 4-tuple (a,b,c,d) followed by a (possibly empty, possibly non-empty) list of 4-tuples xs. The pattern on the second line is a nested pattern: it first matches the list against a pattern like (x:xs), i.e. element x followed by rest of list xs; and then it matches x against the 4-tuple structure.
Below, I'll give some basic examples. Note that you can also write this with standard higher-order functions, such as filter and map, and I'm deliberaty not mentioning things like #-patterns and strictness. I do not recommend doing it like this, but it's just to give you an idea!
When you want to sum the first part of the tuples, you could do it like this:
sum4 :: [(Int,Int,Int,Int)] -> Int
sum4 [] = 0
sum4 ((a,b,c,d):xs) = a + sum4 xs
If you want to filter out the tuples where all of a,b,c and d are even:
filter4allEven :: [(Int,Int,Int,Int)] -> [(Int,Int,Int,Int)]
filter4allEven [] = []
filter4allEven ((a,b,c,d):xs)
| all even [a,b,c,d] = (a,b,c,d) : filter4AllEven xs
| otherwise = filter4AllEven xs
(If the use of all confuses you, just read even a && even b && even c && even d)
And finally, here's a function that returns all the even tuple components (tuples themselves can't be even!) in the same order as they appear in the argument list:
evenTupleComponents :: [(Int,Int,Int,Int)] -> [Int]
evenTupleComponents [] = []
evenTupleComponents ((a,b,c,d):xs) = [x | x <- [a,b,c,d], even x] ++ evenTupleComponents
Once you do a couple of exercises like these, you'll see why using standard functions is a good idea, since they all follow similar patterns, like applying a function to each tuple separately, including or excluding a tuple when it has some property or, more generally, giving a base value for the empty list and a combining function for the recursive case. For instance, I would write evenTupleComponents as evenTupleComponents = filter even . concatMap (\(a,b,c,d) -> [a,b,c,d]), but that's a different story :)