Something wrong with a Haskell List - list

I do not know what happened with this.
I have a list
L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
and i need a function that gives me this:
L = [[1, 4, 7],[2, 5, 8],[3, 6, 9]]
until now i have this:
rotar2 [ ] = [ ]
rotar2 l = [map head l] ++ rotar2(map tail l)
and it works but not at all..
it sends me this error:
[[1,4,7],[2,5,8],[3,6,9],[
Program error: pattern match failure: head []
what should i do?

You are repeatedly taking the heads and tails of every list in your function's input. Eventually, one of these lists will only have the empty list left as a tail and attempting to take the head of that empty list will then fail.
rotar2 [[1,2,3],[4,5,6],[7,8,9]]
= [[1,4,7]] ++ rotar2 [[2,3], [5,6], [8,9]]
= [[1,4,7]] ++ [[2,5,8]] ++ rotar2 [[3], [6], [9]]
= [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ rotar2 [[],[],[]]
= [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ [head [],head[],head []] ++ ...
= [[1,4,7],[2,5,8],[3,6,9],[⊥,⊥,⊥],...]
Transpose
The function rotar2 that you are trying to define is usually called transpose and can be implemented rather straightforwardly as
transpose :: [[a]] -> [[a]]
transpose [] = repeat []
transpose (xs : xss) = zipWith (:) xs (transpose xss)
The idea is that a nonempty list of lists, say [[1,2,3],[4,5,6],[7,8,9]], can be transposed inductively by first transposing its tail [[4,5,6],[7,8,9]], yielding [[4,7],[5,8],[6,9]], and then prepending the elements of the head list [1,2,3] to the elements of the transposed tail:
[ 1 : [4,7] , 2 : [5,8] , 3 : [6,9] ]
Hence:
> transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1,4,7],[2,5,8],[3,6,9]]
In the standard libraries, this function is exported by the module Data.List.

You can redefine the transpose function in one line:
transpose = getZipList . traverse ZipList
All the definitions and instances are in the Control.Applicative and Data.Traversable modules. It's the same definition as in the Stefan Holdermans answer modulo typeclasses and wrapping-unwrapping stuff.

Related

map function with previous and next list element in Haskell

I have a list e.g. [1,2,3,4,5] where I need to know not only the current element but also the predecessor and successor elements. Is there any map function which can be used as follows:
map (\prev cur next -> ...) [1,2,3,4,5]
Or maybe you have another idea to solve the problem?
You can use tails and then process each three items:
import Data.List(tails)
[ … | (x₀ : x₁ : x₂ : _) <- tails [1, 2, 3, 4, 5] ]
for example:
import Data.List(tails)
[ (x₀, x₁, x₂) | (x₀ : x₁ : x₂ : _) <- tails [1, 2, 3, 4, 5] ]
Here the (x₀, x₁, x₂) parameters will thus work with (1, 2, 3), (2, 3, 4) and (3, 4, 5).
You can zip the lists together and drop one element of each
>> as = [1..5]
>> zipWith3 (\prev cur next -> (prev, cur, next)) as (drop 1 as) (drop 2 as)
[(1,2,3),(2,3,4),(3,4,5)]

SML - Error: types of if branches do not agree

I am trying to code an SML function that returns an array of results in listViolations(L1, L2). I specifically want to cross reference each element with eachother O(n^2), and check to see if the selection conflicts with one another. To visualize: [[1, 2], [2, 3]] is option 1 and [[3, 2], [2, 1]] is option two. I would call listViolations like this: listViolations([[[1, 2], [2, 3]], [[3, 2], [2, 1]]]).
The plan of action would be to :
fun listViolations(L1, L2) =
if L1 = [] orelse L2 = []
then 0
else totalViolations(transitive_closure(hd(L1)),path(hd(L2)))::[] # listViolations(L1, tl(L2))::[] # listViolations(tl(L1), L2)::[];
Here I am checking the head of both lists, and passing on the tails of both recursively, in hopes of creating something like this: [3, 0 , 0].
Although I am getting this error when I declare the function:
stdIn:726.5-728.136 Error: types of if branches do not agree [overload conflict]
then branch: [int ty]
else branch: int list
in expression:
if (L1 = nil) orelse (L2 = nil)
then 0
else totalViolations (transitive_closure <exp>,path <exp>) ::
nil # listViolations <exp> :: <exp> # <exp>
I provided all my other functions below to show that there's nothing wrong with them, I just want to know if there's something im doing wrong. I know for a fact that
totalViolations(transitive_closure(hd(L1)),path(hd(L2)))
listViolations(L1, tl(L2))::[]
listViolations(tl(L1), L2)::[];
return integers. How do I make a list out of it and return it within this function? Thank you in advance.
//[1, 2] , [1, 2, 3] = 0
//[3, 2] , [1, 2, 3] = 1
fun violation(T, P) =
if indexOf(hd(T), P) < indexOf(hd(tl(T)), P) then 0
else 1;
//[[1, 2], [2, 3]] , [1, 2, 3] = 0
//[[3, 2], [2, 1]] , [1, 2, 3] = 2
fun totalViolations(TS, P) =
if TS = [] then 0
else violation(hd(TS), P) + totalViolations(tl(TS), P);
//[[1, 2],[2, 3]] -> [1, 2, 3]
fun path(L) =
if L = [] orelse L =[[]]
then []
else union(hd(L),path(tl(L)));
// [[1, 2],[2, 3]] -> [[1, 2],[2, 3], [1, 3]]
fun transitive_closure(L) = union(L, remove([], closure(L, L)));
Additional Code:
fun len(L) = if (L=nil) then 0 else 1+length(tl(L));
fun remove(x, L) =
if L = [] then []
else if x = hd(L) then remove(x, tl(L))
else hd(L)::remove(x, tl(L));
fun transitive(L1, L2) =
if len(L1) = 2 andalso len(L2) = 2 andalso tl(L1) = hd(L2)::[]
then hd(L1)::tl(L2)
else [];
fun closure(L1, L2) =
if (L1 = [[]] orelse L2 = [[]] orelse L1 = [] orelse L2 = [])
then [[]]
else if len(L1) = 1 andalso len(L2) = 1
then transitive(hd(L1), hd(L2))::[]
else
union( union(closure(tl(L1), L2), closure(L1, tl(L2))), transitive(hd(L1), hd(L2))::[]);
The then branch of your if is an int while the else branch is a list of ints. To form a list in the former, write [0] (which is just short for 0::[]). Also, the result of the recursive calls in the other branch is already expected to return a list, so the consing with [] is wrong, because it forms a list of lists.
More tips: never compare to the empty list, that will force the element type to be an equality type. Use the null predicate instead. Even better (and much more readable), avoid null, hd, and tail altogether and use pattern matching.

haskell quick sort, why the first let uses <= instead of <?

quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerOrEqual = [a | a <- xs, a <= x]
larger = [a | a <- xs, a > x]
in quicksort smallerOrEqual ++ [x] ++ larger
main = do
let a = [ 5, 1, 9, 4, 6, 7, 3]
print $ quicksort a
in Haskell quick sort, why the first let uses <= instead of <? I think <= will duplicate that x many times. Why not?
I think <= will duplicate that x many times
No, it will not. Let us understand what exactly is happening here. You are basically partitioning your list into three parts.
List of numbers smaller than or equal to the pivot element (excluding the first element, since that is the pivot element)
The pivot element itself (the first element in the list)
List of numbers greater than the pivot element
So, in your case, the partitioned list becomes like this
[1, 4, 3] ++ [5] ++ [9, 6, 7]
Consider a case like this, quicksort [5, 1, 5, 9, 8, 5, 3, 6, 4]. Then, your program will partition it into something like this
smallerOrEqual ++ [x] ++ larger
Since smallerOrEqual and larger work with xs, which doesn't have the x, there is no duplication as such. Now, the partitioned list, after the filtering, becomes
[1, 5, 5, 3, 4] ++ [5] ++ [9, 8, 6]
See? There is no duplication, just partitioning.
Note: Your program has a serious bug. Check this line
quicksort smallerOrEqual ++ [x] ++ larger
It basically works like this
(quicksort smallerOrEqual) ++ [x] ++ larger
So, the larger list is never sorted. You recursively have to sort both the smaller list and the greater list and finally merge them in to one. So, it should have been
(quicksort smallerOrEqual) ++ [x] ++ (quicksort larger)
which can be written without the brackets like this
quicksort smallerOrEqual ++ [x] ++ quicksort larger

Can't seem to get my head around the 'list difference' (\\) operator

I have heard the term 'list difference' (\\) operator in Haskell but still don't quite know how to get my head around it. Any examples or ideas?
The (\\) operator (and the difference function) implements set difference, so, if you have two lists, a and b, it returns only those elements of a that are not in b, as illustrated:
Simply put, it takes two lists, goes through the second and for each item, removes the first instance of the same item from the first list.
> [1..10] \\ [2, 3, 5, 8]
[1,4,6,7,9,10]
> [1, 2, 1, 2, 1, 2] \\ [2]
[1,1,2,1,2]
> [1, 2, 1, 2, 1, 2] \\ [2, 2]
[1,1,1,2]
> [1, 2, 1, 2, 1, 2] \\ [2, 2, 1]
[1,1,2]
xs \\ ys is all the elements in xs that are not in ys. Maybe a list comprehension will clarify this:
xs \\ ys = [ x | x <- xs, x `notElem` ys ]
or, if you could do this in Haskell,
xs \\ ys = [ x | x `elem` xs, x `notElem` ys ]
This comes from set theory's set difference. The basic idea is that you are "subtracting" one collection of elements from another, hence the term "difference".
Suppose, you have a list of things, for example cities. Let's take for instance this list:
a = ["London","Brussels","Tokio","Los Angeles","Berlin","Beijing"]
Now you want to remove all cities that are in Europe. You know, that those cities are in Europe:
b = ["Glasgow","Paris","Bern","London","Madrid","Amsterdam","Berlin","Brussels"]
To get a list of cities in a, that are not in Europe, so that are not in b, you can use (\\):
a \\ b = ["Tokio","Los Angeles","Beijing"]

Does Haskell have List Slices (i.e. Python)?

Does Haskell have similar syntactic sugar to Python List Slices?
For instance in Python:
x = ['a','b','c','d']
x[1:3]
gives the characters from index 1 to index 2 included (or to index 3 excluded):
['b','c']
I know Haskell has the (!!) function for specific indices, but is there an equivalent "slicing" or list range function?
There's no built-in function to slice a list, but you can easily write one yourself using drop and take:
slice :: Int -> Int -> [a] -> [a]
slice from to xs = take (to - from + 1) (drop from xs)
It should be pointed out that since Haskell lists are singly linked lists (while python lists are arrays), creating sublists like that will be O(to), not O(to - from) like in python (assuming of course that the whole list actually gets evaluated - otherwise Haskell's laziness takes effect).
If you are trying to match Python "lists" (which isn't a list, as others note) then you might want to use the Haskell vector package which does have a built in slice. Also, Vector can be evaluated in parallel, which I think is really cool.
No syntactic sugar. In cases where it's needed, you can just take and drop.
take 2 $ drop 1 $ "abcd" -- gives "bc"
I don't think one is included, but you could write one fairly simply:
slice start end = take (end - start + 1) . drop start
Of course, with the precondition that start and end are in-bounds, and end >= start.
Python slices also support step:
>>> range(10)[::2]
[0, 2, 4, 6, 8]
>>> range(10)[2:8:2]
[2, 4, 6]
So inspired by Dan Burton's dropping every Nth element I implemented a slice with step. It works on infinite lists!
takeStep :: Int -> [a] -> [a]
takeStep _ [] = []
takeStep n (x:xs) = x : takeStep n (drop (n-1) xs)
slice :: Int -> Int -> Int -> [a] -> [a]
slice start stop step = takeStep step . take (stop - start) . drop start
However, Python also supports negative start and stop (it counts from end of list) and negative step (it reverses the list, stop becomes start and vice versa, and steps thru the list).
from pprint import pprint # enter all of this into Python interpreter
pprint([range(10)[ 2: 6], # [2, 3, 4, 5]
range(10)[ 6: 2:-1], # [6, 5, 4, 3]
range(10)[ 6: 2:-2], # [6, 4]
range(10)[-8: 6], # [2, 3, 4, 5]
range(10)[ 2:-4], # [2, 3, 4, 5]
range(10)[-8:-4], # [2, 3, 4, 5]
range(10)[ 6:-8:-1], # [6, 5, 4, 3]
range(10)[-4: 2:-1], # [6, 5, 4, 3]
range(10)[-4:-8:-1]]) # [6, 5, 4, 3]]
How do I implement that in Haskell? I need to reverse the list if the step is negative, start counting start and stop from the end of the list if these are negative, and keep in mind that the resulting list should contain elements with indexes start <= k < stop (with positive step) or start >= k > stop (with negative step).
takeStep :: Int -> [a] -> [a]
takeStep _ [] = []
takeStep n (x:xs)
| n >= 0 = x : takeStep n (drop (n-1) xs)
| otherwise = takeStep (-n) (reverse xs)
slice :: Int -> Int -> Int -> [a] -> [a]
slice a e d xs = z . y . x $ xs -- a:start, e:stop, d:step
where a' = if a >= 0 then a else (length xs + a)
e' = if e >= 0 then e else (length xs + e)
x = if d >= 0 then drop a' else drop e'
y = if d >= 0 then take (e'-a') else take (a'-e'+1)
z = takeStep d
test :: IO () -- slice works exactly in both languages
test = forM_ t (putStrLn . show)
where xs = [0..9]
t = [slice 2 6 1 xs, -- [2, 3, 4, 5]
slice 6 2 (-1) xs, -- [6, 5, 4, 3]
slice 6 2 (-2) xs, -- [6, 4]
slice (-8) 6 1 xs, -- [2, 3, 4, 5]
slice 2 (-4) 1 xs, -- [2, 3, 4, 5]
slice (-8)(-4) 1 xs, -- [2, 3, 4, 5]
slice 6 (-8)(-1) xs, -- [6, 5, 4, 3]
slice (-4) 2 (-1) xs, -- [6, 5, 4, 3]
slice (-4)(-8)(-1) xs] -- [6, 5, 4, 3]
The algorithm still works with infinite lists given positive arguments, but with negative step it returns an empty list (theoretically, it still could return a reversed sublist) and with negative start or stop it enters an infinite loop. So be careful with negative arguments.
I had a similar problem and used a list comprehension:
-- Where lst is an arbitrary list and indc is a list of indices
[lst!!x|x<-[1..]] -- all of lst
[lst!!x|x<-[1,3..]] -- odd-indexed elements of lst
[lst!!x|x<-indc]
Perhaps not as tidy as python's slices, but it does the job. Note that indc can be in any order an need not be contiguous.
As noted, Haskell's use of LINKED lists makes this function O(n) where n is the maximum index accessed as opposed to python's slicing which depends on the number of values accessed.
Disclaimer: I am still new to Haskell and I welcome any corrections.
When I want to emulate a Python range (from m to n) in Haskell, I use a combination of drop & take:
In Python:
print("Hello, World"[2:9]) # prints: "llo, Wo"
In Haskell:
print (drop 2 $ take 9 "Hello, World!") -- prints: "llo, Wo"
-- This is the same:
print (drop 2 (take 9 "Hello, World!")) -- prints: "llo, Wo"
You can, of course, wrap this in a function to make it behave more like Python. For example, if you define the !!! operator to be:
(!!!) array (m, n) = drop m $ take n array
then you will be able to slice it up like:
"Hello, World!" !!! (2, 9) -- evaluates to "llo, Wo"
and use it in another function like this:
print $ "Hello, World!" !!! (2, 9) -- prints: "llo, Wo"
I hope this helps, Jon W.
Another way to do this is with the function splitAt from Data.List -- I find it makes it a little easier to read and understand than using take and drop -- but that's just personal preference:
import Data.List
slice :: Int -> Int -> [a] -> [a]
slice start stop xs = fst $ splitAt (stop - start) (snd $ splitAt start xs)
For example:
Prelude Data.List> slice 0 2 [1, 2, 3, 4, 5, 6]
[1,2]
Prelude Data.List> slice 0 0 [1, 2, 3, 4, 5, 6]
[]
Prelude Data.List> slice 5 2 [1, 2, 3, 4, 5, 6]
[]
Prelude Data.List> slice 1 4 [1, 2, 3, 4, 5, 6]
[2,3,4]
Prelude Data.List> slice 5 7 [1, 2, 3, 4, 5, 6]
[6]
Prelude Data.List> slice 6 10 [1, 2, 3, 4, 5, 6]
[]
This should be equivalent to
let slice' start stop xs = take (stop - start) $ drop start xs
which will certainly be more efficient, but which I find a little more confusing than thinking about the indices where the list is split into front and back halves.
Why not use already existing Data.Vector.slice together with Data.Vector.fromList and Data.Vector.toList (see https://stackoverflow.com/a/8530351/9443841)
import Data.Vector ( fromList, slice, toList )
import Data.Function ( (&) )
vSlice :: Int -> Int -> [a] -> [a]
vSlice start len xs =
xs
& fromList
& slice start len
& toList
I've wrote this code that works for negative numbers as well, like Python's list slicing, except for reversing lists, which I find unrelated to list slicing:
slice :: Int -> Int -> [a] -> [a]
slice 0 x arr
| x < 0 = slice 0 ((length arr)+(x)) arr
| x == (length arr) = arr
| otherwise = slice 0 (x) (init arr)
slice x y arr
| x < 0 = slice ((length arr)+x) y arr
| y < 0 = slice x ((length arr)+y) arr
| otherwise = slice (x-1) (y-1) (tail arr)
main = do
print(slice (-3) (-1) [3, 4, 29, 4, 6]) -- [29,4]
print(slice (2) (-1) [35, 345, 23, 24, 69, 2, 34, 523]) -- [23,24,69,32,34]
print(slice 2 5 [34, 5, 5, 3, 43, 4, 23] ) -- [5,3,43]
Obviously my foldl version loses against the take-drop approach, but maybe someone sees a way to improve it?
slice from to = reverse.snd.foldl build ((from, to + 1), []) where
build res#((_, 0), _) _ = res
build ((0, to), xs) x = ((0, to - 1), x:xs)
build ((from, to), xs) _ = ((from - 1, to - 1), xs)
sublist start length = take length . snd . splitAt start
slice start end = snd .splitAt start . take end