Haskell optimizing infinite list implementation - list

My code gives the wanted result but I wonder if there is a better way to code this. This is the given example:
pair [ 1 , 2 , 3 , 4 , 5 , 6 , ... ]
[ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] , ... ]
and the given code:
pair::[a] -> [[a]]
pair =
My solution:
pair :: [a] -> [[a]]
pair (x:y:xs) = ((x:y:[]):[]) ++ pair xs

Using the cons operator : will be much more performant than concatenating lists:
pair :: [a] -> [[a]]
pair (x:y:xs) = [x, y] : pair xs
The reasoning is that lists in Haskell are linked lists where each item points to the next until the end of the list. Pushes and Pops are cheap when done at the head of the list because you are only pointing the head at the head of an existing list.
When you concatenate two linked list, you are essentially rebuilding the complete first list so that its last element can point at the first element of the second list.
The performance gain is minor in your example since you only have two elements in your list, but as a general rule, if you're dealing with operations on the head of the list, it's almost always going to be more performant to use cons.

Related

how to add a number in a 2D list with specific index in haskell

I'm beginner in haskell and I tried to add a number in a 2D list with specific index in haskell but I don't know how to do
example i have this:
[[],[],[]]
and I would like to put a number (3) in the index 1 like this
[[],[3],[]]
I tried this
[array !! 1] ++ [[3]]
but it doesn't work
As you may have noticed in your foray so far, Haskell isn't like many other languages in that it is generally immutable, so trying to change a value, especially in a deeply nested structure like that, isn't the easiest thing. [array !! 1] would give you a nested list [[]] but this is not mutable, so any manipulations you do this structure won't be reflected in the original array, it'll be a separate copy.
(There are specialized environments where you can do local mutability, as with e.g. Vectors in the ST monad, but these are an exception.)
For what you're trying to do, you'll have to deconstruct the list to get it to a point where you can easily make the modification, then reconstruct the final structure from the (modified) parts.
The splitAt function looks like it will help you with this: it takes a list and separates it into two parts at the index you give it.
let array = [[],[],[]]
splitAt 1 array
will give you
([[]], [[],[]])
This helps you by getting you closer to the list you want, the middle nested list.
Let's do a destructuring bind to be able to reconstruct your final list later:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
Next, you'll need to get at the sub-list you want, which is the first item in the end list:
desired = head end
Now you can make your modification -- note, this will produce a new list, it won't modify the one that's there:
desired' = 3:desired
Now we need to put this back into the end list. Unfortunately, the end list is still the original value of [[],[]], so we'll have to replace the head of this with our desired' to make it right:
end' = desired' : (tail end)
This drops the empty sub-list at the beginning and affixes the modified list in its place.
Now all that's left is to recombine the modified end' with the original beginning:
in beginning ++ end'
making the whole snippet:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
desired = head end
desired' = 3:desired
end' = desired' : (tail end)
in beginning ++ end'
or, if you're entering all these as commands in the REPL:
let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'
As paul mentions, things in Haskell are immutable. What you want to do must be done not be modifying the list in place, but by destructuring the list, transforming one of its parts, and restructuring the list with this changed part. One way of destructuring (via splitAt) is put forth there; I'd like to offer another.
Lists in Haskell are defined as follows:
data [] a = [] | a : [a]
This reads "A list of a is either empty or an a followed by a list of a". (:) is pronounced "cons" for "constructor", and with it, you can create nonempty lists.
1 : [] -> [1]
1 : [2,3] -> [1,2,3]
1 : 2 : 3 : [] -> [1,2,3]
This goes both ways, thanks to pattern matching. If you have a list [1,2,3], matching it to x : xs will bind its head 1 to the name x and its tail [2,3] to xs. As you can see, we've destructured the list into the two pieces that were initially used to create it. We can then operate on those pieces before putting the list back together:
λ> let x : xs = [1,2,3]
λ> let y = x - 5
λ> y : xs
[-4,2,3]
So in your case, we can match the initial list to x : y : z : [], compute w = y ++ [3], and construct our new list:
λ> let x : y : z : [] = [[],[],[]]
λ> let w = y ++ [3]
λ> [x,w,z]
[[],[3],[]]
But that's not very extensible, and it doesn't solve the problem you pose ("with specific index"). What if later on we want to change the thousandth item of a list? I'm not too keen on matching that many pieces. Fortunately, we know a little something about lists—index n in list xs is index n+1 in list x:xs. So we can recurse, moving one step along the list and decrementing our index each step of the way:
foo :: Int -> [[Int]] -> [[Int]]
foo 0 (x:xs) = TODO -- Index 0 is x. We have arrived; here, we concatenate with [3] before restructuring the list.
foo n (x:xs) = x : foo (n-1) xs
foo n [] = TODO -- Up to you how you would like to handle invalid indices. Consider the function error.
Implement the first of those three yourself, assuming you're operating on index zero. Make sure you understand the recursive call in the second. Then read on.
Now, this works. It's not all that useful, though—it performs a predetermined computation on a specified item in a list of one particular type. It's time to generalize. What we want is a function of the following type signature:
bar :: (a -> a) -> Int -> [a] -> [a]
where bar f n xs applies the transformation f to the value at index n in the list xs. With this, we can implement the function from before:
foo n xs = bar (++[3]) n xs
foo = bar (++[3]) -- Alternatively, with partial application
And believe it or not, changing the foo you already wrote into the much more useful bar is a very simple task. Give it a try!

How to move 1 element of a List to right or left in Haskell?

Hi I have been looking for an answer but could not find one. Lets say that we have a list like [1,10,4,5,3] how can I shift 5 to left so that this list becomes [1,10,5,4,3].
I tried to swapElementsAt by finding the index of that element but it looks very insufficient.
swapElementsAt :: Int -> [a] -> [a]
swapElementsAt n list = let (beg, a:b:rest) = splitAt (n-1) list in beg ++ b:a:rest
It works like
λ> swapElementsAt 3 [1,10,4,5,3]
[1,10,5,4,3]
Consider how would you write this function if you were to traverse the input list from left to right looking at a very local vicinity of the beginning of the list (since that's what you can easily pattern-match on).
The most straightforward way would be to pattern-match on the first two elements, and check if the second element matches your pattern. If so, just build a new list by swapping these elements and appending the remainder of the list, otherwise, go recursively over the rest.
In code:
swapElem :: Eq a => a -> [a] -> [a]
swapElem e (x:y:xs) | y == e = y : x : xs
swapElem e (x:xs) = x : swapElem e xs
swapElem _ [] = []
The first pattern only matches when there are at least two elements in the list, and the second element is equal to the desired one. If there are less elements or the second element is not the right one, it will fall through to the second pattern, that matches arbitrary non-empty list and calls swapElem on the remainder of the list. The third pattern is there to provide the base recursion case of an empty input list.
Note this code only changes the first occurrence of the target element:
Prelude> swapElem 5 [1, 10, 4, 5, 3]
[1,10,5,4,3]
Prelude> swapElem 5 [1, 10, 5, 4, 5, 3]
[1,5,10,4,5,3]
How would you change it so that it left-shifts all 5s?
Also, the answer depends on what exactly is your input. The answer by #Scarabyte considers the case where you're given the position of the target element, while this approach instead considers the element that you want to shift left.

head function for empty list issue

I want to use 'head' function inside map.
The problem is the 'head' function only accepts non-empty list.
I have list of list:
let ll =[["dog", "cat"], ["pig", "cow"], []]
I need to iterate the list of list twice
let listOne = filter(\x -> if length x > 0) ll
map(\x -> head x) listOne
I'm wondering whether I can iterate the list of list once or put a "if condition" inside the map without the 'filter'
Any suggestion would be appreciated.
Yes, in fact you can write it as a list comprehension statement, and use pattern matching instead:
result = [ h | (h:_) <- ll ]
or as a function:
heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]
So here we use the pattern (h:_) which matches all non-empty lists, and we directly obtain the head h of such list and add it to the list. If you use a pattern in list comprehension (on the left side of the left arrow <-, it will skip the elements that do not match the pattern).
This is also more safe than using length, since length will get stuck into an infinite loop if you are working with infinite lists. Furthermore by using patterns over the non-total head function, we have more syntactical guarantees that this function will work (yes, once the non-empty elements are filtered, we are of course certain that head will not result in errors, but we only know this because we have information about the head function).
Note that your attempt will result in a syntax error, since you use an if, without a then and else part.
Alternatively, we can, like #DanielWagner says, write the heads function differently, for instance using:
heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll
or by using the bind of the list monad:
heads :: [[a]] -> [a]
heads = (take 1 =<<)
or we can transpose the 2d list. In that case the first row contains all the heads of the lists. Since it is however not guaranteed that there is such a row, we can append an empty list at the end, like:
heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.

How do I get a list item by index in elm?

I got a list, and now I want the nth item. In Haskell I would use !!, but I can't find an elm variant of that.
Elm added arrays in 0.12.1, and the implementation was massively overhauled in 0.19 to improve correctness and performance.
import Array
myArray = Array.fromList [1..5]
myItem = Array.get 2 myArray
Arrays are zero-indexed. Negative indices are not supported currently (bummer, I know).
Note that myItem : Maybe Int. Elm does everything it can to avoid runtime errors, so out of bounds access returns an explicit Nothing.
If you find yourself looking to index into a list rather than take the head and tail, you should consider using an array.
Array documentation
There is no equivalent of this in Elm.
You could of course implement it yourself.
(Note: This is not a "total" function, so it creates an exception when the index is out of range).
infixl 9 !!
(!!) : [a] -> Int -> a
xs !! n = head (drop n xs)
A better way would be to define a total function, using the Maybe data type.
infixl 9 !!
(!!) : [a] -> Int -> Maybe a
xs !! n =
if | n < 0 -> Nothing
| otherwise -> case (xs,n) of
([],_) -> Nothing
(x::xs,0) -> Just x
(_::xs,n) -> xs !! (n-1)
I've used this:
(!!): Int -> List a -> Maybe a
(!!) index list = -- 3 [ 1, 2, 3, 4, 5, 6 ]
if (List.length list) >= index then
List.take index list -- [ 1, 2, 3 ]
|> List.reverse -- [ 3, 2, 1 ]
|> List.head -- Just 3
else
Nothing
Of course you get a Maybe and you need to unwrap it when you use this function. There is not guarantee that your list will not be empty, or that you ask for a imposible index (like 1000) - so that's why elm compiler forces you to account for that case.
main =
let
fifthElement =
case 5 !! [1,2,3,4,255,6] of // not sure how would you use it in Haskell?! But look's nice as infix function. (inspired by #Daniël Heres)
Just a ->
a
Nothing ->
-1
in
div []
[ text <| toString fifthElement ] // 255