Understanding haskell code - haskell

I am new to haskell. Can someone explain how I can interpret this line of code in haskell :
filter (\(_, (varible1, _)) -> variable1 `notElem` [something1, something2])

-- Filter a list...
filter
-- ...of nested tuples where the first element of the second element of the tuple...
(\(_, (variable1, _)) ->
-- ...is not an element of [something1, something2]
variable1 `notElem` [something1, something2])
(_, (varible1, _)) deconstructs a nested tuple, and names one of the elements. Look up deconstruction to understand what's going on there.

Let's start at the beginning.
\p -> e
is a lambda abstraction (an anonymous function) where p is a pattern and e is an expression that may use variables that appear in p.
(_, (variable1, _))
is a pattern constructed from the constructor (,), which constructs pairs. Here are some pairs:
(1, 2)
("Hello", "world!")
(1, (2, 3))
Here are some patterns which match pairs, used in lambda abstractions.
\(x, y) -> x
\(x,(y,z)) -> y
The second pattern matches a pair like (1, (2, 3)) and gives the first element of the second element. In this case, it would give 2. Its shape is like the pattern in your question, but what about the _ in your pattern?
_ is a valid variable name (variables can begin with underscores or lower-case letters). It is used to mean "a variable we don't use". The pattern (_, (y, _)) is like the pattern (x, (y, z)) except the only variable that has a name is y. Normally, you aren't allowed to reuse variable names in patterns. (x,x) is in invalid pattern, for instance. You are allowed to reuse _ though because Haskell knows you intend to throw that value away.
Now we can understand the expression
\(_, (variable1, _)) -> variable1
It is a function of type (a, (b, c)) -> b which takes a pair whose second element is itself a pair and gives the first element of the second element.
Now we need to understand
variable1 `notElem` [something1, something2]
To understand this expression, we need to know what the backticks do. Surrounding an identifier in backticks turns it into an infix operator. Infix operators are usually spelled with symbols, like x + y and xs ++ ys. The backticks let us convert normal identifiers, like notElem, into infix operators. This means that the above expression is the same as
notElem variable1 [something1, something2]
notElem is a function which takes an item and a list of items of the same type and gives True if the item does not appear in the list and False otherwise. It is the opposite of the elem test for membership.
Finally, filter. filter p xs is a function that takes a predicate p (i.e., a function which returns a Bool) and uses it to filter the list xs. filter gives a new list where elements (call them x) are included if p x is true. This filters the list of xs and gives a new list whose elements are those for which the predicate is true. For example,
> filter even [1,2,3,4]
[2,4]
So, we have
filter -- filter a list
(\(_, (variable1, _)) -- by matching on the first element
-- of the second element of a pair
-- and calling it 'variable1'
-> variable1 `notElem` [something1, something2])
-- and giving `True` if the element
-- is neither 'something1' nor 'something2'
This gives a function which takes a list of pairs whose second element is a pair and filters it to a list of pairs whose second element is a pair whose first element is neither something1 nor something2.
We can apply it, calling it f below:
f = filter (\(_, (varible1, _)) -> variable1 `notElem` [something1, something2])
> f [(1,(something1,2)), (1,(something3,3))]
[(1,(something3,3))]

Related

What is the difference between square brackets and parentheses in regard to lists?

As the title implies, I am unsure about the difference between square brackets and parentheses in regard to lists.
Two versions of Haskell's insert defined, one using square brackets, the other using parentheses:
insert' :: Int -> [Int] -> [Int]
insert' y [] = [y]
insert' y (x:xs) | y <= x = y:x:xs | otherwise = x : insert' y xs
----
insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
What is the reason the second definition of insert' doesn't work?
The error message it gives, for anyone wondering:
test.hs:3:12: error:
• Couldn't match expected type ‘Int’ with actual type ‘[Int]’
• In the pattern: x : xs
In the pattern: [x : xs]
In an equation for ‘insert'’:
insert' y [x : xs]
| y <= x = y : x : xs
| otherwise = x : insert' y xs
|
3 | insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
|
As in almost all other languages, parentheses in Haskell don't really do anything. They help the parser know which things you intended to group together, and that's it; they don't change the meaning of the thing that's inside them, and if the parser could magically guess which way you intended to group things at every choice point we wouldn't need them at all. So all of these patterns behave exactly the same:
x
(x)
((x))
(((((((((x)))))))))
All of these patterns are also exactly the same:
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
Sometimes we must use one of the later ones -- like (x:xs) -- instead of the first one -- x:xs -- to inform the parser that we intended these things to be grouped together. But the parentheses don't otherwise change anything about what the pattern means.
Square brackets, on the other hand, are used for constructing lists. They have an actual run-time meaning: they allocate a new data structure in memory and initialize it. For example, 3 is a number, but [3] is a list with a single element, [3,4] is a list with two elements, [[3]] is a list of lists, and so on. The same behavior applies to patterns:
x -- match anything (even a list!) and bind x to its value
[x] -- match a list with a single element, and bind x to that element's value
[x,y] -- match a list with two elements, and bind x and y to those elements' values
[[x]] -- match a nested list; the outer and inner lists both have one element; bind x to the first element's first element
Now we can address your specific example. The pattern x:xs is a pattern that matches any list with at least one element, binding x to that first element and xs to the rest of the list. The pattern (x:xs) does exactly the same thing. The pattern [x:xs], on the other hand, matches a list with exactly one element, because there are square brackets; the only element of that list is then matched against the pattern x:xs, with the behavior described above.
One consequence of this is that x:xs can match lists with any type of element -- say, Int -- but [x:xs] can only match lists whose elements are lists.
(x:xs) as a pattern will match any non-empty list with x its head and xs its tail.
[x:xs] as a pattern will match a singleton list -- a list containing exactly one item -- which is a non-empty list, matching the pattern (x:xs). The pattern [x:xs] is in fact equivalent to the pattern [(x:xs)]. It is a nested pattern, and Haskell allows that. The outer pattern matches a singleton list, and the inner pattern matches a non-empty list. The parentheses in this position are optional.
That's why your second definition implies the type of the second argument is [[a]], but you've declared it to be [Int]. And Int can't match [a]. (That a is also determined to be an Int, since you compare x and y, and y the first argument is declared to be an Int, but that doesn't change anything).
[ [a] ]
[ Int ]
----------------
***mismatch***

Pattern matching expects round braces for non empty list and not square brackets

In Haskell why pattern matching expects list to have round braces but not square braces when it is not empty? Why does it not follow the same convention when it tries to pattern match with empty list [] (square braces). Shouldn't the round braces reserved exclusively for tuples?
For example - below does not work
third :: Integral a => [a] -> a
third xs = case xs of
[] -> 0
[_:_:x:_] -> x
otherwise -> 0
But this works
third :: Integral a => [a] -> a
third xs = case xs of
[] -> 0
(_:_:x:_) -> x
otherwise -> 0
There is actually to way to write a list
[1, 2, 3]
Or
1:2:3:[]
(Note the :[] at the end). The first one is the traditional way of writing a list but is actually just a shortcut to write the second one. : denotes the cons operator and [] denotes an empty list (which appears to be the same as []in the first version).3:[]means , take 3 and prepend it to the empty list (which is then equivalent to [3]).2:3:[]means : prepend 2 to the previous list (which is also equivalent to 2:[3]. And finally 1:2:3:[] is equivalent to 1:[2,3]. So
[1, 2, 3]
1:[2,3]
1:2:[3]
1:2:3:[]
are equivalent. However [1:2:3:[]] is equivalent to [[1,2,3]] not [1,2,3].
So, when you pattern match on (x:_), you are saying : I want a list starting with x and I don't care of it's tail (therefore it can be ANY length). When you write [x:_], you are actually writting [(x:_)], which means, I want a list of ONE elements, this element start with x. This could be correct, but the list you are pattern matching on is not a list of a but a list of list of a ([[a]]) which doesn't match your type signature.
The list pattern [p1, ..., pn] matches an n-element list where each element matches the patterns p1 through pn respectively. The pattern [p] is a list pattern with only one element, so it matches a list with exactly one element that matches the pattern p. So [_:_:x:_] matches a list containing exactly one element and that element must be a list matching the pattern _:_:x:_.
So why doesn't the same logic apply to (p) and tuples? That is, why doesn't (_:_:x:_) match a one-element tuple that contains a list? Because there's no such thing as a one-element tuple. Parentheses in Haskell are overloaded in a way: When they contain a comma, they denote a tuple; if they contain nothing (()), they denote the unit value; otherwise they're just used for grouping.
So the pattern (_:_:x:_) just matches the pattern _:_:x:_. The parentheses are usually just used to avoid ambiguity (f x:y = ... would be interpreted as (f x):y = ..., not f (x:y) =...), but in this case they're actually redundant. You could just write:
third xs = case xs of
[] -> 0
_:_:x:_ -> x
otherwise -> 0

Haskell - How does a pattern match fail in a list comprehension?

I'm learning Haskell with Miran Lipovaca's "Learn You a Haskell for Great Good!". In page 82 it says
If a pattern match fails, the list comprehension will just move on to the next element, and the element that failed won’t be included in the resulting list.
Example:
ghci> let xs = [(1,3),(4,3),(2,4),(5,3),(5,6),(3,1)]
ghci> [a+b | (a, b) <- xs]
[4,7,6,8,11,4]
My question is how does a pattern match fail?
What does he mean by that? I really don't get it. It could be because of my weak english. I please you for an example because I think the book doesn't give any example for failing pattern match.
I thought about something like if the list contains a type that couldn't be processed by the list comprehension then it moves to the next element but if I change the list in this way:
let xs = [(1,3),(4,3),(2,4),(5,3),True,(5,6)]
Then it doesn't even compile because it "couldn't match expected type"...
Here are a few cases of failing pattern matching in list comprehensions, demoed in GHCi:
Prelude> [ () | True <- [True, False,True] ]
[(),()]
Prelude> [ x | (x, True) <- [(1,True), (2,False), (3,True)] ]
[1,3]
Prelude> [ x+1 | Left x <- [Left 1, Right "Hello", Right "world", Left 2] ]
[2,3]
Note that some patterns can never fail, e.g. x, (x,y), or (x,(a,b),z). This is because they match types having only a constructor, which has to match being the only one.
In general, pattern matching involves multiple branches, e.g.
case someValue of
Left x -> ...
Right y -> ...
foo Nothing = ...
foo (Just x) = ...
In these cases, if we forget to handle a constructor, we get a runtime error when that case occurs. (Turning on warnings helps in avoiding this!).
In list comprehensions generators p <- ..., instead, we can only specify one pattern. However, a special rule applies: failure of pattern matching is not an error, but is simply ignored.
That's not an example of pattern-match failure (the tuple pattern matches always). This would be an example:
Prelude> xs = [Just (1,3), Just (4,3), Nothing, Just (5,3), Nothing]
Prelude> [a+b | Just (a, b) <- xs]
[4,7,8]
Here, the pattern Just (a, b) matches only the elements Just (1,3), Just (4,3) and Just (5,3), but not the Nothings, so these positions just don't turn up in the final list.

What does (:) do in Haskell? [duplicate]

This question already has answers here:
What does the : infix operator do in Haskell?
(4 answers)
Closed 8 years ago.
I've tried looking it up in hoogle and other various haskell dictionaries, but I can't find it. I was under the impression that it prepends, but I'm starting to see it in ways I haven't before and I've started second guessing myself.
For example, this is one of the questions that I don't understand:
(3 points) Fill in the blank with a pattern such that fun1 [(5,6),(7,8)] returns
5 and fun1 [(10,20),(30,40),(50,60)] returns 10:
and the answer is apparently:
((y,_):_)
fun1 _____________ = y
But I am so confused by this. I understand that the underscores mean that you don't really care about what the types of those are, but I don't understand what the (:) does in this answer.
While the other answers correctly explain what : is they don't quite answer the question - in the answer you have in your question : isn't used as a function, but as a constructor to pattern match on. fun (x:xs) = x means "if the argument is of the format (x:xs) give me the x". Pattern matching is used to "pull apart" complex types based on their constructors in Haskell.
In particular, since : is a list constructor you can pull apart lists with :
(conceptually list is defined as data [] a = [] | (:) a [a], although you're not gonna get this to compile because it's builtin syntax).
A non list example: We could define a datatype data F a b = A a | B b. This would create a type F that's parameterized with two types a and b and two constructors A and B with the types a -> F a b and b -> F a b respectively.
You could then write functions that use pattern matching to get at the contained values, like
isA (A _) = True -- this value was constructed with A, so it is an A
isA (B _) = False -- this value was constructed with B so it is not an A
or
getA (A a) = a -- this value was constructed with A so we can get an a out of it
getA (B _) = undefined -- ohps! We can't get an a back here cause we don't have one!
It is a List constructor function. It is used for prepending any value in front of the list.
ghci> 2 : [3,4]
[2,3,4]
It is just another Haskell function. You can also see it's type in ghci:
ghci> :t (:)
(:) :: a -> [a] -> [a]
Regarding your question, the answer is like this ((y,_):_) because it is being used in pattern matching. The first _ is the second element of the pair and the second _ pattern matches a list.
This may help you:
ghci> (5,6):[(7,8)]
[(5,6),(7,8)]
: is the list constructor of type a -> [a] -> [a]. It is usually used infix. but you can use it as prefix if you surround it with parentheses as you did. Just like any infix operation. (E.g. (+) 4 5 == 4 + 5)
So (:) a as is the same as a:as
Every constructor in Haskell can be also used do deconstruct a value of the type if constructs in a pattern match:
f x:xs = xs
would for example define a function that takes a non empty list and returns the tail. It would fail on an empty list because the empty list is constructed by the nullary constructor []. You could make f total by adding that second constructor to the match.
f [] = []
I guess your confusion comes from the fact that in haskell there is syntactic sugar that allows you to write lists in a more convenient way. Instead of (1:(2:(3:[]))) you can write [1,2,3] which is expanded into the former by the compiler.
In addition to the answers of what (:) function does, please, bear in mind that in the context of your question : is used as a deconstructor.
It is better to view (:) as a constructor. Then, just like any other data constructor, it can be used to introspect the contents of the value. Examples are:
f (Just x) = x -- extracts the value wrapped into Maybe a
f (x:_) = x -- extracts the value wrapped into a list, [a]
f ((x,_):_) = x -- extracts the value wrapped into a tuple in the list of tuples
In all these cases Just, : and (,) are constructors. The same syntax can be used to construct or deconstruct the values - depending on the context of the expression. Compare:
f x = Just x -- wraps x into Maybe a
f x xs = x:xs -- wraps x into a list, [a]
f x y z = (x,y):z -- wraps x into a tuple in the list of tuples
To understand what fun1 does, let's first look at another function:
f (x:xs) = x
If you pass this function a list such as [5,12,33], it will match x to 5, and xs to [12,33]. The function just returns x, i.e. the first element. So this function is basically the same as head. Since we don't actually use the value xs, we can rewrite the function as:
f (x:_) = x
Now let's look at fun1, but a slightly modified version.
fun1 ((y,z):xs) = y
If we pass this function the list [(5,6),(7,8)], it will match (y,z) to the pair (5,6) and xs to [(7,8)]. So now y is 5, and that's the value we return. Again, since we don't use z or xs, we can write the function as:
fun1 ((y,_):_) = y

Haskell code errors - I dont understand what it is asking for

First time poster, but this site has helped me alot.
I am trying to learn Haskell.
This is the question i'm asked to answer.
Write a function that takes a list (length >=2) of pairs of length and returns the first component of the second element in the list. So, when provided with [(5,’b’), (1,’c’), (6,’a’)], it will return 1.
I have done this myself.
listtwo :: [([a],b)] -> [a]
listtwo [] = []
listtwo [(a,b)] = fst (head (tail [(a,b)]))
I am trying to take a list of lists tuples I believe and return the 1st element from the 2nd item in the list. I know if you take out the [(a,b)]'s and replace the second [(a,b)] with a list like the one in the question it works fine. But when I try to make this function work for ANY list of tuples. I get errors.
Error I recieve
<interactive>:1:27:
No instance for (Num [a0])
arising from the literal `6'
Possible fix: add an instance declaration for (Num [a0])
In the expression: 6
In the expression: (6, 'a')
In the first argument of `listtwo', namely
`[(5, 'b'), (1, 'c'), (6, 'a')]'
So i'm asking if anyone can help me deciver the errors and mabye explain what I am doing wrong (don't give me the answer, cant learn that way).
Appriciate the help, might have more questions if this gets answered. Thank you very much in advance!
You say that you want a function that returns the first component of the second element of the list. The best way to write this function will be by pattern matching. But first, let's think about its type.
Say you want a list of tuples of (Int,Char). This is written as [(Int,Char)]. If you want a list of 2-tuples of arbitrary type, you replace the types Int and Char with type variables, so you end up with the type [(a,b)].
Your function needs to take something of this type, and return the first component of the second element of the list. All of the first components of the tuples have type a, so your return type must be a as well. So your function's type signature is
f :: [(a,b)] -> a
Now, how do we write this function? The best way is to use pattern matching. This is a neat way to extract the components of a data structure without having to use accessors (aka getters, if you come from an object-oriented background). Let's say we have a function g :: [a] -> a which returns the third component of a list. You could write
g :: [a] -> a
g xs = head (tail (tail xs))
but that looks pretty nasty. Another way is to pattern match. A list with three elements [x,y,z] can be constructed by doing x : y : z : [] where x, y and z are all of type a (remember that the operator : adds items to the front of a list). So we can write:
g :: [a] -> a
g (x : y : z : []) = z
But there's a problem with this - it only works on lists of length three, because our pattern says "Match a list of three elements with the empty list tacked on the end." Instead, we could use the pattern x : y : z : rest, where now rest matches the rest of the list:
g :: [a] -> a
g (x : y : z : rest) = z
where our pattern now says "Match a list of three elements followed by anything else at all." In fact, we can make it simpler. We aren't going to use the values x, y or rest so we can replace them with the Haskell pattern _ (underscore). This matches anything, and makes us promise that we aren't going to use that value:
g :: [a] -> a
g (_ : _ : z : _) = z
How can we use this to solve your problem? Well, if you had a list matching the pattern (w,x) : (y,z) : rest you would want to return y. So you can write:
f :: [(a,b)] -> a
f ( (w,x) : (y,z) : rest ) = y
which will work fine. However, you don't care about the first pair at all, so you can replace (w,x) with _. You also don't care about the second element of the second tuple or the rest of the list, so you can replace them with _ as well, getting:
f :: [(a,b)] -> a
f ( _ : (y,_) : _) = y
Checking it in ghci:
ghci> f [(5,'b'),(1,'c'),(6,'a')]
1
So it behaves as you expected it to.

Resources