Haskell Noob question: What's wrong with my append function? - haskell

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.

Related

How do i achieve [x if func(x,lst) for x in list] in haskell?

Okay so I come from a python background and am new with haskell and doing an assignment. I am done with the question itself but my logic/code looks ugly and wanted to know of ways to improve it. What I want to do is iterate over a list with that list as argument to call another function.
Assuming that I want to achieve the following in haskell.
input = [1,2,2,3,3,4,5]
output = [1,4,5] #occurs Once
so i want to go from x->y
normally how I'd do it would be
def checksOnce(input):
lst = []
for val in input:
if occursOnce(val,input):
lst.append(val)
print(lst)
How do i do that iterating in haskell? I have a function that works fine for occursOnce which takes a value and list and returns a bool just like python.
checksOnce :: [Int] -> [Int] -> [Int]
checksOnce [] lst = []
checksOnce (x:xs) lst
| occursOnce x lst = [x] ++ checksOnce xs lst
| otherwise = checksOnce xs lst
and something like mainFunc lst = checksOnce lst lst to call the above function.
The above works fine and is sufficient as far as my hw goes, but passing the same argument Once is redundant! How do i go from checksOnce :: [Int] -> [Int] -> [Int] to checksOnce :: [Int] -> [Int] and use just one list to iterate over like the above python code instead of passing the same list Once to the function?
Thanks
Haskell has list comprehensions, so you can do:
\f xs -> [x | x <- xs, f x xs]
You can also do this with a filter:
\f xs -> filter (\x -> f x xs) xs
The simplest, and probably most idiomatic, way to write this function in Haskell would be to use filter:
checksTwice :: (Eq a) => [a] -> [a] -- you can keep it as [Int] -> [Int] if you like, but this more general type signature is better because the function works on any type that can be compared for equality
checksTwice xs = filter (\x -> occursTwice x xs) xs
Or if you prefer (although the gain is debatable), rewriting the lambda in "point-free" style:
checksTwice :: (Eq a) => [a] -> [a]
checksTwice xs = filter (flip occursTwice xs) xs
(Which is exactly the answer suggested in the comments by #user2407038 - apologies for "stealing" your answer)
Well just like you did in your Python you'd want to have the variable lst only visible to the function checksTwice and not a parameter. Haskell throws some people for a loop what with it's lack of looping primitives - the solution is usually a helper function of a higher order function.
checksOnce :: [Int] -> [Int]
checksOnce xs = go xs xs
where go [] _ = []
go (x:xs) lst
| occursOnce x lst = x : go xs lst
| otherwise = go xs lst
But this pattern, including x if and only if f x is just a filter so...
checksOnce x = filter (`occursOnce` lst) xs
As #RobinZigmond noted, this still has a bug vs the behavior you desire.

(x:xs) pattern Haskell logic

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.

Apply a function to every element in a list to every element in another list - Haskell

My ultimate goal is to find if a list y contains all the elements of list x (I'm checking if x is a subset of y sort of thing)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
This doesn't work, and I know it's because z is a list still. I'm trying to make sense of this.
I think I may have to use the elem function, but I'm not sure how to split x into chars that I can compare separately through y.
I'm ashamed to say that I've been working on this simple problem for an hour and a half.
Checking whether all elements of xs are elements of ys is very straightforward. Loop through xs, and for each element, check if it is in ys:
subset xs ys = all (\x -> elem x ys) xs
You could also use the list difference function (\\). If you have list y and list x, and you want to check that all elements of x are in y, then x \\ y will return a new list with the elements of x that are not in y. If all the elements of x are in y, the returned list will be empty.
For example, if your list y is [1,2,3,4,5] and your list x is [2,4], you can do:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
If list y is [1,2,3,4,5] and list x is [2,4,6], then:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
Easy way to reason about subsets is to use sets as the data type.
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
Then it's as simple as:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
Let's break this down into two subproblems:
Find if a value is a member of a list;
Use the solution to #1 to test whether every value in a list is in the second one.
For the first subproblem there is a library function already:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
Lists are a Foldable type, so you can use this function with lists for t and it would have the following type:
elem :: (Eq a) => a -> [a] -> Bool
EXERCISE: Write your own version of elem, specialized to work with lists (don't worry about the Foldable stuff now).
So now, to tackle #2, one first step would be this:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
After that, we need to go from the list of individual boolean results to just one boolean. There's a standard library function that does that as well:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
EXERCISE: write your own version of and, specialized to lists:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
With these tools, now we can write subset:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
Although a more experienced Haskeller would probably write it like this:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...where every is another standard library function that is just a shortcut for the combination of map and and:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p

basic Haskell: defining sorting function by recursion

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.

Remove an item from a list in Haskell

How can I delete an item from a list in Haskell?
I've got this code but it doesn't seems to work. The concept its, I've got 2 lists, the aList will always have just one element. bList will always have the element that its in aList. So I want to delete the element from bList and at the end, output the new list without that item. Could give some hints please?
Thanks
removeFromList :: aList -> bList -> finalList
removeFromList [] _ = []
removeFromList (y:ys) (x:xs)
| y == x = removeFromDatabase y xs
| otherwise = y : removeFromDatabase y xs
removeFromList :: Eq a => [a] -> [a] -> [a]
removeFromList _ [] = []
removeFromList (y:ys) (x:xs)
| y == x = removeFromList [y] xs
| otherwise = x : removeFromList [y] xs
There are a few issues:
The first list should contain the element but you appear to be getting it from the second in the first clause, so it should be:
removeFromList _ [] = []
Secondly, you need to recreate the list containing the single element when making the recursive calls i.e. removeFromList [y] xs
Thirdly the list types should be the same, and you need the Eq constraint for ==
As long as you always have a single element in aList, I'd propose another solution:
removeFromList :: Eq a => [a] -> [a] -> [a]
removeFromList [elem] = filter (== elem)
Or, if you have only one occurence of that element:
import Data.List
removeFromList [elem] = delete elem
But remember, it will fail if the first argument somehow appears to be empty or have more than one element.
Problems in your code:
You use aList and bList not as argument names, but as type variables in the function signature, which are too general (equivalent to removeFromList :: a -> b -> c)
When you recursively call the function, you pass y which is a single element, not a list.

Resources