Let's say there is a simple function:
maximum' :: (Ord a) => [a] -> a
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs) = max x (maximum' xs)
I understand the idea and what (x:xs) does. As it was explained in details here
What do the parentheses signify in (x:xs) when pattern matching?
but there is one little thing that I cannot get out of my head. Since cons: operator appends x to a list xs, why is it that x is the first element of function argument list and xs is the tail when we use (x:xs)??? as if (x:xs) calls head and tail on argument list.
This is just an instance of the general pattern that the constructor for a type is both used to construct elements of that type and to deconstruct. If you wrote
data MyList a = Empty | Cons a (MyList a)
you'd write
maximum' :: (Ord a) => MyList a -> a
maximum' Empty = error "maximum of empty list"
maximum' (Cons x Empty) = x
maximum' (Cons x xs) = max x (maximum' xs)
Except that lists are actually defined equivalently to
data [a] = [] | a:as
so, just as with other data types, : is used both to construct and to deconstruct nonempty lists.
The cons operator doesn't append, it prepends. That is x : xs produces a list that contains x as its first element and xs as the rest. Therefore the pattern x : xs likewise matches a list with x as the first element and xs as the rest.
Related
Im new to haskell and Im writing a function that compares two sequences and reports the length of the prefix they have in common. This is what I have so far but it doesn't work for all cases.
commonLen :: Eq a => [a] -> [a] -> Int
commonLen (x:xs) [] = 0
commonLen (x:xs) (y:ys) | x==y = 1+(commonLen xs ys)
| otherwise = commonLen xs ys
Any ideas where im going wrong? Any help would be appreciated
You should not recurse in case x is different from y. In that case we return 0:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen [] _ = 0
commonLen _ [] = 0
commonLen (x:xs) (y:ys) | x == y = 1 + commonLen xs ys
| otherwise = 0 -- ← return 0
You also can avoid the explicit recursion, and work with:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen xs ys = length (takeWhile id (zipWith (==) xs ys))
here we iterate over both lists concurrently, and compare the elements. We thus make a list of Bools that is True if the elements of the two lists match. Then we use takeWhile to take elements as long as the item is True, and we use length to determine the number of elements in that list. Due to Haskell's laziness, we will never evaluate the entire list if one of the elements differs from the corresponding element in the other list.
So I have slight problem with sorting function. I need to define (using recursion) a function i, that takes as an argument a list of arguments a (this list needs to belong to Ord), which outputs ordered list of elements of type a.
Example:
i [3,2,1] = [1,2,3]
I have managed to come with this solution:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs : x
But it doesn't compute, outputting many errors. What is wrong?
Let me give you some hints to get you started. First of all, let's fix the formatting:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs : x
This throws an error which says:
In the first argument of ‘(:)’, namely ‘i xs’
In the expression: i xs : x
Now, this expression i xs : x is problematic. The type of (:) is (:) :: a -> [a] -> [a]. But in your expression you are passing a list instead of a value. What you meant to use was possibly ++. Using that fixes the compile error:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs ++ [x]
Now, if you try it in ghci, you will get a runtime exception:
ghci> i [3,2,1]
*** Exception: Prelude.head: empty list
Can you guess why ? That's because you haven't handled the case where the list is of length 1. So handling the case will give you this:
i :: Ord a => [a] -> [a]
i [] = []
i (x:[]) = [x]
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs ++ [x]
Now, you may think that this works:
ghci> i [3,2,1]
[1,2,3]
ghci> i [3,1,2]
[1,2,3]
But it doesn't actually work, because there is a flaw in your algorithm. Just comparing the first two elements of the list won't give you an sorted array.
ghci> i [2,1,3]
[1,3,2]
I hope this is enough to get you started.
I have been getting my hands around coding in Haskell, but couldn't grasp the idea of implementing union function.
I have also found some function definition embedded inside the Haskell platform. but the problem is I need a neat and understandable way to make it work.
Anyone can help me with that?
Assuming you're talking about union :: Eq a => [a] -> [a] -> [a] which takes two input lists and returns a third list which contains all of the elements of each argument list, then it's defined in Data.List which is in the base package.
In the source it's divided into two functions, the generalized function unionBy which takes a custom definition of equality (a function of type equal to (==) :: a -> a -> Bool) and then defines the one that uses the Eq typeclass by passing in (==) as a concrete implementation of equality.
union :: (Eq a) => [a] -> [a] -> [a]
union = unionBy (==)
We can substitute (==) into the unionBy code, though, as Haskell lets us use equational reasoning.
union = unionBy (==)
-- so...
union :: Eq a => [a] -> [a] -> [a]
union xs ys = xs ++ foldl (flip (deleteBy (==))) (nubBy (==) ys) xs
This same pattern occurs twice more in the definition of unionBy in deleteBy and nubBy, both of which follow the same convention. delete removes an element from a list and nub returns a list of unique elements. We'll simplify the definition again to eliminate all traces of (==) and simply assume that the elements a have Eq defined.
union xs ys = xs ++ foldl (flip delete) (nub ys) xs
Now the definition is perhaps more readable. The union of xs and ys is xs appended to the unique ("nubbed") values of ys which have been processed by foldl (flip delete) _ xs. The net result of that foldl is to one by one try to delete each element of xs from (nub ys). What that ends up meaning is that union xs ys is xs appended to each unique element from ys less those in xs.
As an aside, with this source in hand we can notice some quirky behavior of union such as how it treats duplicates in the first argument differently from the second argument
union [1,1,2] [2] == [1,1,2]
union [2] [1,1,2] == [2,1]
which is a bit of a letdown, a result of using [] to represent a Set-like notion of union. However, if we view the results using Set.fromList then we're fine.
xs, ys :: Eq a => [a]
Set.fromList (xs `union` ys) == Set.fromList xs `Set.union` Set.fromList ys
which also gives us another definition of union
union xs ys = Set.toList (Set.fromList xs `Set.union` Set.fromList ys)
So how does that foldl trick work? Let's unpack the definition of foldl to see, again abusing equational reasoning.
union xs ys = xs ++ (case xs of
[] -> nub ys
(x:xs') -> foldl (flip delete) (delete x (nub ys)) xs'
)
which should make the trick more evident—it cycles over the elements of xs, deleting them one by one from (nub ys).
While hopefully this helped to make the code in union a bit more clear, the real take home should be that equational reasoning is a powerful tool for dissecting Haskell code. Don't be afraid to simplify code directly by manually inlining the definition of a function.
I am not sure if this union meets your requirements but it is rather simple.
I needed my own function to remove duplicates.
rmdups ls = [d|(z,d)<- zip [0..] ls,notElem d $ take z ls]
It does the same as any recursive function of the same purpose.
union l1 l2 = let l = l1 ++ l2 in rmdups l
I may have misinterpreted the question, but this was a post I found as I was trying to find how to write my own union function. I understand there is one built in but as someone who was trying to learn Haskell that doesn't help at all. These were the functions I wrote to make it work.
memberSet :: Int -> [Int] -> Bool
memberSet x [] = False
memberSet x (y:ys)
| x == y = True
| otherwise = memberSet x ys
unionSet :: [Int] -> [Int] -> [Int]
unionSet [] [] = []
unionSet (x:xs) [] = (x:xs)
unionSet [] (y:ys) = (y:ys)
unionSet (x:xs) (y:ys)
| memberSet y (x:xs) = unionSet (x:xs) ys
| otherwise = y : unionSet (x:xs) ys
main = do
print (unionSet [1,2,3] [2,5,3,4])
Member set checks if an element is present in a list (again I know there is a built in function to do this but I'm trying to learn). And there union set checks if the first elem of the second list is in the first list, if its not it adds it to a list and recursively calls itself. If it is in the first list, it skips that elem and recursively calls itself.
One problem I don't think anyone has addressed is that set union and intersection must be commutative and associative (Tom Apostol Calculus, p. 14).
λ> (Data.List.union [1,1,2] [2]) == (Data.List.union [2] [1,1,2])
False
λ> import Data.Set (Set, lookupMin, lookupMax)
λ> import qualified Data.Set as Set
λ> Set.union (Set.fromList [1, 3, 5, 7]) (Set.fromList [0, 2, 4, 6])
fromList [0,1,2,3,4,5,6,7]
λ> Set.union (Set.fromList [0, 2, 4, 6]) (Set.fromList [1, 3, 5, 7])
fromList [0,1,2,3,4,5,6,7]
So Data.List is not aware, but few more experiments would seem to demonstrate that Haskell Data.Set is aware. So another nail in the coffin of lists as sets, although I suppose we could kludge something further with lists.
I have a little alternative implementation of groupBy, which is more useful to me than the version in Data.List, because it doesn't require the test to be an equivalence relation:
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' f = foldr step []
where step x [] = [[x]]
step x (xs:xss)
| x `f` head xs = (x:xs):xss
| otherwise = [x]:xs:xss
However, it's too eager and won't start computing for inputs like groupBy' (<) [1,2,3,2,3,4,1,undefined]. I have read the HaskellWiki and Wikibooks articles which explain why certain things, like pattern matches, can make functions less lazy, and I think I understand most of the examples given there. Still, I don't understand why this function can't start producing output until it hits the undefined. Are the pattern matches causing this behavior?
Since I have just read those articles, it's maybe lack of experience that makes me fail to apply what I read there to my example code. So, how could this particular implementation be changed in order to behave more lazily?
The key problem is that you know that step x xss will always produce a result of the form (x:_):_, but you are "hiding" this behind the pattern matches, so Haskell is forced to evaluate those first to determine which case of step to choose before it even sees those constructors.
In general, for foldr f x to be able to produce any output before reaching the end of the list, f must be able to produce some output before examining its second argument.
We can fix this by splitting step into two, so that we can produce the two (:) constructors before doing the pattern matching on the second argument.
groupBy' f = foldr step []
where step x xss = let (ys, yss) = step' x xss in (x:ys):yss
step' x [] = ([], [])
step' x (xs:xss) | f x (head xs) = (xs, xss)
| otherwise = ([], xs:xss)
This is about as lazy as you can get it.
*Main> groupBy' (<) [1, 2, 3, 2, 3, 4, 1, undefined]
[[1,2,3],[2,3,4],[1*** Exception: Prelude.undefined
foldr step [] [1,2,3,...] will expand to step 1 (foldr step [] [2,3]). Now step needs to decide whether to go in its first case or the second. For that it needs to know whether foldr step [] [2,3,...] evaluates to an empty list. For that it needs to know whether step 2 (foldr step [] [3,...]) returns the empty list (which it never will, but Haskell does not know that). This goes on until the end of the list is reached (and if the list doesn't have an end, it goes on forever).
It is difficult for me to understand what your code will do when f is not an equivalence relation, but I guess that you want something like the following code:
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' f [] = []
groupBy' f [x] = [[x]]
groupBy' f (x : xs)
| x `f` head xs = (x : head l) : tail l
| otherwise = [x] : l
where
l = groupBy' f xs
or equivalently without using head or tail:
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' f [] = []
groupBy' f (x : xs) = hd : tl
where
(hd, tl) = go x xs
go x [] = ([x], [])
go x xs#(x' : xs')
| x `f` x' = (x : hd', tl')
| otherwise = ([x], hd' : tl')
where
(hd', tl') = go x' xs'
I'm trying to write a Haskell append function... Here's what I have:
myappend :: [a] -> [a] -> [a]
myappend [] x = x
myappend [x:xs] y = x : myappend xs y
But it's giving me an error:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `myappend'
So, obviously there's something wrong with it but I can't see it... What's wrong with my append function?
The constructors of the type [a] are:
[] The empty list
(:) Cons operator (just a regular infix constructor)
So, you must use:
myappend :: [a] -> [a] -> [a]
myappend [] x = x
myappend (x:xs) y = x : myappend xs y
The syntax
[x:xs]
is pretty much equivalent to
[(x:xs)]
which matches a list with one element, a non-empty list, and has type
[(x:xs)] :: [[a]]
I recommend reading this page if you want to understand the constructor and pattern matching concept.
The pattern in the second case of the function should just be (x:xs), not [x:xs]:
myappend (x:xs) y = x : myappend xs y
x:xs matches an element followed by a list, the parenthesis are just there to make it syntactically clear what belongs to that pattern. [x:xs] would match a list containing x:xs.
There should be no [] brackets in
myappend (x:xs) y = x : (myappend xs y)
[1,2,3] and 1:2:3:[] are different ways of defining the same list.
So that [x:xs] matches one item list consisting of another list.