Where did the haskell list difference operator (\\) go? - list

Am I missing something? It seems I don't have the list difference operator defined...
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
Prelude> "Hello World!" \\ "ell W"
<interactive>:1:16: error:
Variable not in scope: (\\) :: [Char] -> [Char] -> t
Prelude> :t (\\)
<interactive>:1:1: error: Variable not in scope: \\
Prelude> :type (\\)
<interactive>:1:1: error: Variable not in scope: \\
Prelude> :type (++)
(++) :: [a] -> [a] -> [a]
Did it get removed? (And if so, where do I look to see that?)

It's in Data.List:
% ghci
GHCi, version 8.4.4: http://www.haskell.org/ghc/ :? for help
Prelude> :t (\\)
<interactive>:1:1: error: Variable not in scope: \\
Prelude> import Data.List
Prelude Data.List> :t (\\)
(\\) :: Eq a => [a] -> [a] -> [a]

Related

infinite type error reversing a list in Haskell

I'm trying to implement the reverse of a list:
myLast :: [a] -> a
myLast [] = error "No end for empty lists!"
myLast [x] = x
myLast (_:xs) = myLast xs
myReverse :: [a] -> [a]
myReverse (x:xs) = myLast xs + myReverse xs
but I get this error:
/workspaces/hask_exercises/exercises/src/Lib.hs:42:32: error:
* Occurs check: cannot construct the infinite type: a ~ [a]
* In the second argument of `(+)', namely `myReverse xs'
In the expression: myLast xs + myReverse xs
In an equation for `myReverse':
myReverse (x : xs) = myLast xs + myReverse xs
* Relevant bindings include
xs :: [a] (bound at src/Lib.hs:42:14)
x :: a (bound at src/Lib.hs:42:12)
myReverse :: [a] -> [a] (bound at src/Lib.hs:41:1)
|
42 | myReverse (x:xs) = myLast xs + myReverse xs
| ^^^^^^^^^^^^
What does it mean that cannot construct the infinite type: a ~ [a]? I get this error a lot and would like to understand what it means.
The (+) :: Num a => a -> a -> a function adds two numbers (of the same type) together. So for example if a ~ Int, it will add two Ints together, but not an Int and a [Int].
But even if the (+) operator for example would prepend an item to a list, it would still not reverse the list correctly: your function has no base case what to do for an empty list, and your recursive list does nothing with the first item x of the list (x:xs).
A simple way to reverse:
myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]
But that is not efficient: appending two items will take linear time in the size of the left list. You can work with an accumulator: a parameter that you each time update when you make a recursive call. This looks like:
myReverse :: [a] -> [a]
myReverse [] = go []
where go ys (x:xs) = …
where go ys [] = …
where filling in the … parts are left as an exercise.
You have
myLast :: [a] -> a
myReverse :: [a] -> [a]
myReverse (x:xs) = myLast xs + myReverse xs
\___a___/ \____[a]___/
(x:xs) :: [a]
---------------
x :: a
xs :: [a] xs :: [a]
myLast :: [a] -> a myReverse :: [a] -> [a]
------------------------- ----------------------------
myLast xs :: a myReverse xs :: [a]
myReverse (x:xs) :: [a]
but
> :t (+)
(+) :: Num a => a -> a -> a
which means that the type of the thing on the left of + and the type of the thing on the right must be the same.
But they can't be: as we just saw above, in your code the first (of myLast xs) is some type a, and the second (of myReverse xs) is [a] the list of those same as.
These two can't be the same, because it would mean
a ~ [a] OK, this is given to us, then
a ~ [a] we can use it, so that
--------------
a ~ [[a]] this must hold;
a ~ [a] we know this, then
--------------
a ~ [[[a]]] this must also hold; and
a ~ [a] ........
-------------- ........
a ~ [[[[a]]]] ........
.........................
and so on ad infinitum, thus making this a an "infinite" type. Hence the error.
You could fix it by replacing the + with
(+++) :: a -> [a] -> [a]
and implementing it to do what you need it to do.
You will also need to fix your off-by-one error whereby you completely ignore the first element in the received input, x.

Adding contents of two different size lists haskell

I am trying to implement a function that sums the contents of two lists. Here is my code:
sum'' :: Num a => [a] -> [a] -> [a]
sum'' [] [] = []
sum'' (x:xs) (y:ys) = (x + y) : sum'' xs ys
If I type in:
sum'' [1,2,3] [4,5,6]
I get [5,7,9], which is what I want. What I am having trouble with is different list sizes. If I type in:
sum'' [] [1,2,3]
I want it to return []. Or
sum'' [1,2] [4,5,6]
I want it to return [5,7]. I am getting this error and do not know why: Non-exhaustive patterns in function sum''.
Any help would be much appreciated.
When defining sum'', you have defined what it means for two empty lists, and for two non-empty lists, but you haven't defined what it means for two lists, only one of which is empty. This is what the compiler is telling you via that error message.
Simply add definitions of what sum'' means whenever left list is empty and the right list is not, and vice versa:
sum'' (x:xs) [] = ...
sum'' [] (y:ys) = ...
Well in Haskell, actually for what you need there is the ZipList type and you may use it to simply do as follows;
import Control.Applicative
addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = getZipList $ (+) <$> ZipList xs <*> ZipList ys
*Main> addLists [3] [1,2,3]
[4]

Using the replicate function in haskell to add to a list

I'm to use the replicate function that Haskell has (replicate 3 'x' = ['x','x','x']) but I'm trying to add it to a list that already exists.
Prelude > let k = ['d','f','g']
Prelude > (replicate 3 'd':k)
but I keep getting the error,
Couldn't match type 'Char' with '[Char]'
Expected type: [[Char]]
Actual type: [Char]
Is there a way to do this?
k and replicate 3 'd' each have a type of [Char].
ghci> :t k
k :: [Char]
ghci> :t replicate 3 'd'
replicate 3 'd' :: [Char]
However, the type of (:) is a -> [a] -> [a]: it takes a single a and adds it to the list of as.
ghci> :t (:)
(:) :: a -> [a] -> [a]
So Haskell's giving you a type error because you can't apply (:) to two things of type [Char]. In other words, you can't put a [Char] inside a [Char].
What we really need is a function of type [a] -> [a] -> [a] which concatenates the two lists. It happens that this function is called (++).
ghci> :t (++)
(++) :: [a] -> [a] -> [a]
ghci> replicate 3 'd' ++ k
"ddddfg"

Haskell: How to return a list of possible splits of a list

I'm trying to write a function named split that takes a list and returns a list of pairs of all the different possiblities to partition it, e.g.
split [4,3,6] = [([],[4,3,6]),([4],[3,6]),([4,3],[6]),([4,3,6],[])]
Now I wrote this
split :: [a] -> [([a],[a])]
split [] = [([],[])]
split (x:xs) = ([],(x:xs)):(zip (map (x:) (map fst split(xs))) (map snd split(xs)))
piece of code and Hugs and the interpreter of my choice gets me this
ERROR file:.\split.hs:3 - Type error in application
*** Expression : map snd split xs
*** Term : map
*** Type : (e -> f) -> [e] -> [f]
*** Does not match : a -> b -> c -> d
error message. What the heck am I doing wrong? Why would (map snd split xs) be of type
(a-> b -> c -> d)?
You've misplaced your parens. Try
split (x:xs) = ([],(x:xs)):(zip (map (x:) (map fst (split xs))) (map snd (split xs)))
Haskell doesn't use parenthesis for function calls in the same way as something like C and Java. When you write map fst split(xs) this is the same as map fst split xs, i.e. the compiler thinks that you are trying to call map with three parameters. Therefore you need to parenthise the call to split like this: map fst (split xs).
What you are effectively trying to write is a simple zipper for a list. The easiest way to implement it is
import Data.List (inits, tails)
split xs = zip (inits xs) (tails xs)
Here's an alternative definition:
splits :: [a] -> [(a, a)]
splits xs = map (flip splitAt xs) [0 .. length xs]
Admittedly, it's not very efficient, but at least it's concise :-)
Another version that's even shorter, and probably more efficient, using inits and tails from Data.List:
splits :: [a] -> [(a, a)]
splits xs = zip (inits xs) (tails xs)
Now let's have a little fun. We can write inits and tails as foldrs, where we use initsA and tailsA to represent what are known as the algebras of the folds:
inits :: [a] -> [[a]]
inits = foldr initsA [[]]
initsA :: a -> [[a]] -> [[a]]
initsA x xss = [] : map (x:) xss
tails :: [a] -> [[a]]
tails = foldr tailsA [[]]
tailsA :: a -> [[a]] -> [[a]]
tailsA x xss = (x : head xss) : xss
Using these algebras, we can further combine them:
splits :: [a] -> [([a], [a])]
splits = foldr splitsA [([], [])]
splitsA :: a -> [([a], [a])] -> [([a], [a])]
splitsA xy xyss = zip (initsA xy xss) (tailsA xy yss)
where (xss, yss) = unzip xyss
So now we have splits defined as a single foldr!

Is there any haskell function to concatenate list with separator?

Is there a function to concatenate elements of a list with a separator?
For example:
> foobar " " ["is","there","such","a","function","?"]
["is there such a function ?"]
Thanks for any reply!
Yes, there is:
Prelude> import Data.List
Prelude Data.List> intercalate " " ["is","there","such","a","function","?"]
"is there such a function ?"
intersperse is a bit more general:
Prelude> import Data.List
Prelude Data.List> concat (intersperse " " ["is","there","such","a","function","?"])
"is there such a function ?"
Also, for the specific case where you want to join with a space character, there is unwords:
Prelude> unwords ["is","there","such","a","function","?"]
"is there such a function ?"
unlines works similarly, only that the strings are imploded using the newline character and that a newline character is also added to the end. (This makes it useful for serializing text files, which must per POSIX standard end with a trailing newline)
It's not hard to write one-liner using foldr
join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
Some other ideas of implementations of intersperse and intercalate, if someone is interested:
myIntersperse :: a -> [a] -> [a]
myIntersperse _ [] = []
myIntersperse e xs = init $ xs >>= (:[e])
myIntercalate :: [a] -> [[a]] -> [a]
myIntercalate e xs = concat $ myIntersperse e xs
xs >>= f is equivalent to concat (map f xs).
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
If you wanted to write your own versions of intercalate and intersperse:
intercalate :: [a] -> [[a]] -> [a]
intercalate s [] = []
intercalate s [x] = x
intercalate s (x:xs) = x ++ s ++ (intercalate s xs)
intersperse :: a -> [a] -> [a]
intersperse s [] = []
intersperse s [x] = [x]
intersperse s (x:xs) = x : s : (intersperse s xs)