How do I change a certain value in a matrix in Haskell? - list

I'm very new to Haskell and haven't fully understood how it works yet.
In the following method I would like to change a certain value in a matrix or as it is realized in Haskell, a list of lists.
setEntry :: [[Int]] -> Int -> Int -> Int -> [[Int]]
setEntry x i j aij =
This is my method so far. I know it's not much but I really don't know how to continue.
The plan is to give it a matrix and then change the value that can be found in the ith line and the jth column to aij.
I'd be very grateful for any kind of help.
Thank you already in advance!

First note that there isn't really any need to make this specific to Int-valued matrices: the signature could just as well be
setMatEntry :: [[a]] -> Int -> Int -> a -> [[a]]
Also, instead of just setting it, you might as well modify it, i.e. the new value to put in could depend on the old, right?
modifyMatEntry :: [[a]] -> Int -> Int -> (a -> a) -> [[a]]
With that you could easily implement the original version as
setMatEntry x i j aij = modifyMatEntry x i j (const aij)
or shorter:
setMatEntry x i j = modifyMatEntry x i j . const
The nice thing about approaching it with a modifier than just a constant to be set it that this composes to nested lists of any depth. I.e. there's no reason to right away go to matrices, you might as well first tackle
modifyListEntry :: [a] -> Int -> (a -> a) -> [a]
and then
modifyMatEntry x i j f = modifyListEntry x i
(\r -> modifyListEntry r j f)
Here, the outer modifyListEntry works with the [a] -> [a] function that uses the inner modifyListEntry with the a -> a function.
Incidentally, this can actually be made shorter if we turn around the order of arguments: I'd recommend this order
modifyListEntry :: Int -> (a->a) -> [a] -> [a]
modifyMatEntry :: Int -> Int -> (a->a) -> [[a]] -> [[a]]
So, now the only thing that isn't completely trivial is modifyListEntry. But it's clear how, in general, to deal with lists – you're going to have clauses of the form
modifyListEntry i f [] = _
modifyListEntry i f (x:xs) = _
...or possibly also pattern match concrete values for the other parameters. Then you'll need to use recursion. Try to figure that out yourself.

Related

Haskell - Append to a list inside a list of lists and return the lists of lists updated

Having spent hours looking for ways to manipulate [[a]] into [[a]], I thought this would be the best solution to my problem. The problem consists of appending a to [a] and returning [[a]] with the new change.
For example: xs = [[a],[b],[c]] and y = d.
I want to append y to xs!!0 . I cannot use xs!!0 ++ y because it will return just [a,d], I know this is because of Haskell's immutability.
How would I go about appending a value to a sublist and returning the list of lists? - [[a,d],[b],[c]] using the example from above to illustrate this.
let { xs = [[1]] ; y = 2 ; zs = [(xs!!0) ++ [y]] } in zs is one example to try at the GHCi prompt.
It returns [[1,2]].
And for the case of e.g. [[1],[2,3],[4]] and the like, we can do
appendToFirst :: [[a]] -> a -> [[a]]
appendToFirst (xs:r) y = (xs ++ [y]) : r
so that
> appendToFirst [[1],[2,3],[4]] 0
[[1,0],[2,3],[4]]
The (xs:r) on the left of the equal sign is a pattern.
The (:) in the ( (...) : r) on the right of the equal sign is a "cons" operation, a data constructor, (:) :: t -> [t] -> [t].
xs is bound to the input list's "head" i.e. its first element, and r is bound to the rest of the input list, in the pattern; and thus xs's value is used in creating the updated version of the list, with the first sublist changed by appending a value to its end, and r remaining as is.
xs ++ [y] creates a new entity, new list, while xs and y continue to refer to the same old values they were defined as. Since Haskell's values and variables are immutable, as you indeed have mentioned.
edit: If you want to add new element at the end of some sublist in the middle, not the first one as shown above, this can be done with e.g. splitAt function, like
appendInTheMiddle :: Int -> a -> [[a]] -> [[a]]
appendInTheMiddle i y xs =
let
(a,b) = splitAt i xs
in
init a ++ [last a ++ [y]] ++ b
Trying it out:
> appendInTheMiddle 2 0 [[1],[2],[3],[4]]
[[1],[2,0],[3],[4]]
Adding the error-handling, bounds checking, and adjusting the indexing if 0-based one is desired (that one would lead to a simpler and faster code, by the way), is left as an exercise for the reader.
Syntactically, this can be streamlined with "view patterns", as
{-# LANGUAGE ViewPatterns #-}
appendInTheMiddle :: Int -> a -> [[a]] -> [[a]]
appendInTheMiddle i y (splitAt i -> (a,b)) =
init a ++ [last a ++ [y]] ++ b

Breaking a list into sublists of a specified size using foldr

I'm taking a functional programming class and I'm having a hard time leaving the OOP mindset behind and finding answers to a lot of my questions.
I have to create a function that takes an ordered list and converts it into specified size sublists using a variation of fold.
This isn't right, but it's what I have:
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| [condition] = foldr (\item subList -> item:subList) [] xs
| otherwise =
I've been searching and I found out that foldr is the variation that works better for what I want, and I think I've understood how fold works, I just don't know how I'll set up the guards so that when length sublist == size haskell resets the accumulator and goes on to the next list.
If I didn't explain myself correctly, here's the result I want:
> splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Thanks!
While Fabián's and chi's answers are entirely correct, there is actually an option to solve this puzzle using foldr. Consider the following code:
splitList :: Int -> [a] -> [[a]]
splitList n =
foldr (\el acc -> case acc of
[] -> [[el]]
(h : t) | length h < n -> (el : h) : t
_ -> [el] : acc
) []
The strategy here is to build up a list by extending its head as long as its length is lesser than desired. This solution has, however, two drawbacks:
It does something slightly different than in your example;
splitList 3 [1..10] produces [[1],[2,3,4],[5,6,7],[8,9,10]]
It's complexity is O(n * length l), as we measure length of up to n–sized list on each of the element which yields linear number of linear operations.
Let's first take care of first issue. In order to start counting at the beginning we need to traverse the list left–to–right, while foldr does it right–to–left. There is a common trick called "continuation passing" which will allow us to reverse the direction of the walk:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse $
foldr (\el cont acc ->
case acc of
[] -> cont [[el]]
(h : t) | length h < n -> cont ((el : h) : t)
_ -> cont ([el] : acc)
) id l []
Here, instead of building the list in the accumulator we build up a function that will transform the list in the right direction. See this question for details. The side effect is reversing the list so we need to counter that by reverse application to the whole list and all of its elements. This goes linearly and tail-recursively tho.
Now let's work on the performance issue. The problem was that the length is linear on casual lists. There are two solutions for this:
Use another structure that caches length for a constant time access
Cache the value by ourselves
Because I guess it is a list exercise, let's go for the latter option:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse . snd $
foldr (\el cont (countAcc, listAcc) ->
case listAcc of
[] -> cont (countAcc, [[el]])
(h : t) | countAcc < n -> cont (countAcc + 1, (el : h) : t)
(h : t) -> cont (1, [el] : (h : t))
) id l (1, [])
Here we extend our computational state with a counter that at each points stores the current length of the list. This gives us a constant check on each element and results in linear time complexity in the end.
A way to simplify this problem would be to split this into multiple functions. There are two things you need to do:
take n elements from the list, and
keep taking from the list as much as possible.
Lets try taking first:
taking :: Int -> [a] -> [a]
taking n [] = undefined
taking n (x:xs) = undefined
If there are no elemensts then we cannot take any more elements so we can only return an empty list, on the other hand if we do have an element then we can think of taking n (x:xs) as x : taking (n-1) xs, we would only need to check that n > 0.
taking n (x:xs)
| n > 0 = x :taking (n-1) xs
| otherwise = []
Now, we need to do that multiple times with the remainder so we should probably also return whatever remains from taking n elements from a list, in this case it would be whatever remains when n = 0 so we could try to adapt it to
| otherwise = ([], x:xs)
and then you would need to modify the type signature to return ([a], [a]) and the other 2 definitions to ensure you do return whatever remained after taking n.
With this approach your splitList would look like:
splitList n [] = []
splitList n l = chunk : splitList n remainder
where (chunk, remainder) = taking n l
Note however that folding would not be appropriate since it "flattens" whatever you are working on, for example given a [Int] you could fold to produce a sum which would be an Int. (foldr :: (a -> b -> b) -> b -> [a] -> b or "foldr function zero list produces an element of the function return type")
You want:
splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Since the "remainder" [10] in on the tail, I recommend you use foldl instead. E.g.
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| size > 0 = foldl go [] xs
| otherwise = error "need a positive size"
where go acc x = ....
What should go do? Essentially, on your example, we must have:
splitList 3 [1..10]
= go (splitList 3 [1..9]) 10
= go [[1,2,3],[4,5,6],[7,8,9]] 10
= [[1,2,3],[4,5,6],[7,8,9],[10]]
splitList 3 [1..9]
= go (splitList 3 [1..8]) 9
= go [[1,2,3],[4,5,6],[7,8]] 9
= [[1,2,3],[4,5,6],[7,8,9]]
splitList 3 [1..8]
= go (splitList 3 [1..7]) 8
= go [[1,2,3],[4,5,6],[7]] 8
= [[1,2,3],[4,5,6],[7,8]]
and
splitList 3 [1]
= go [] 1
= [[1]]
Hence, go acc x should
check if acc is empty, if so, produce a singleton list [[x]].
otherwise, check the last list in acc:
if its length is less than size, append x
otherwise, append a new list [x] to acc
Try doing this by hand on your example to understand all the cases.
This will not be efficient, but it will work.
You don't really need the Ord a constraint.
Checking the accumulator's first sublist's length would lead to information flow from the right and the first chunk ending up the shorter one, potentially, instead of the last. Such function won't work on infinite lists either (not to mention the foldl-based variants).
A standard way to arrange for the information flow from the left with foldr is using an additional argument. The general scheme is
subLists n xs = foldr g z xs n
where
g x r i = cons x i (r (i-1))
....
The i argument to cons will guide its decision as to where to add the current element into. The i-1 decrements the counter on the way forward from the left, instead of on the way back from the right. z must have the same type as r and as the foldr itself as a whole, so,
z _ = [[]]
This means there must be a post-processing step, and some edge cases must be handled as well,
subLists n xs = post . foldr g z xs $ n
where
z _ = [[]]
g x r i | i == 1 = cons x i (r n)
g x r i = cons x i (r (i-1))
....
cons must be lazy enough not to force the results of the recursive call prematurely.
I leave it as an exercise finishing this up.
For a simpler version with a pre-processing step instead, see this recent answer of mine.
Just going to give another answer: this is quite similar to trying to write groupBy as a fold, and actually has a couple gotchas w.r.t. laziness that you have to bear in mind for an efficient and correct implementation. The following is the fastest version I found that maintains all the relevant laziness properties:
splitList :: Int -> [a] -> [[a]]
splitList m xs = snd (foldr f (const ([],[])) xs 1)
where
f x a i
| i <= 1 = let (ys,zs) = a m in ([], (x : ys) : zs)
| otherwise = let (ys,zs) = a (i-1) in (x : ys , zs)
The ys and the zs gotten from the recursive processing of the rest of list indicate the first and the rest of the groups into which the rest of the list will be broken up, by said recursive processing. So we either prepend the current element before that first subgroup if it is still shorter than needed, or we prepend before the first subgroup when it is just right and start a new, empty subgroup.

Haskell:create list of last elements of each list in list

I need to define the function in Haskell's
which for a given list of lists will create a list of its last elements.
For example for [[1,2],[3,4]] it should return [2,4]
I tried to use pattern matching but ite returns only the last list :
lastElement :: [[a]] -> [a]
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
it gives me [3,4]
Problem
You are on the right track, the problem is that your code is not recursing. A recursive function on lists is usually of the form
f :: [a] -> [b]
f [] = y
f (x:xs) = y : f xs
After y is evaluated, that result is ":ed" to the recursive call. Now try to make your code so something similar. Also note that you don't need the lastElement [x] case, it's just plain reduntant for the recursion. However, this only applies some function to every element. You will also need a function f :: [a] -> a to get that last element from one single list. Your function as of now does just that, but there is a standard library function for that. Have a look at Hoogle: you can search library functions by type or description
Better Alternative
In this case, I would use a list comprehension as I think it would be more clear to read. Have a look at that as well
Best Alternative
Haskell being a functional language, it allows you to think more about what change to need to apply to your data, rather than what steps do you need to achieve. If you know them, you can use higher order function for this. In particular, the function map :: (a -> b) -> [a] -> [b]. As you can guess from this type definition, map takes a function, and applies it to every element of a list. It looks like you already know the last function, so you can use that:
lastElements :: [[a]] -> [a]
lastElements = map last
Look how neat and simple this code is now; no need to think about what the recursion does, you just see that it takes the last element from each list.
I will assume that you have beginner skills in Haskell and try to explain better what you are doing wrong.
lastElement :: [[a]] -> [a]
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
In this function, you are receiving a list of elements and returning the last of it. Occurs that those elements are lists too. In that way, applying lastElement [[1,2],[3,4]] will give to you his last element how is the list [3,4]. Since you need to enter a list [x,y,z] in which x y and z are lists and you wanna return [last of x, last of y, last of z], we need two things:
1. A function which receives a list of Int and return his last element
2. Apply this function to a (list of (lists of a)) [[a]]
To make (1) we can easily modify your function lastElement just like this:
lastElement :: [a] -> a
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
Now, lastElement receives one list and return its last element.
To make (2) we just need to create a mapping function like this:
mapping :: ([a] -> a) -> [[a]] -> [a]
mapping _ [] = []
mapping f (x:xs) = (f x) : (mapping f xs)
In that way, you can call mapping lastElement [[1,2],[3,4]] that will give you [2,4].
I need to say that none of this is needed if you knew two functions which is last who do the same as (1) and map who do the same as (2). Knowing this, you can do like Lorenzo already done above:
lastElements :: [[a]] -> [a]
lastElements = map last

Replacing Nth character in String array in Haskell

I am new to Haskell and functional programming in general. I am trying to implement a function to take a list like this
["abc", "def", "ghi"]
and want to be able to replace the xth character in the yth element for example
replaceChar 1 2 'd' arr
would produce
["abc", "ded", "ghi"]
So essentially the first parameter is the element and the second is the position of the string, the third is the character and last is the [String].
The signature of this function looks like this:
replaceChar :: Int -> Int -> Char -> [String] -> [String]
Any help would be appreciated. Thanks!
First a note: while your signature is perfectly fine, you really don't use the fact that you're dealing with character strings, it could just as well be lists of any other type. It's usually a good idea1 to manifest that in your signature by using a completely generic type variable (lowercase letter) instead of Char:
replaceAtXY :: Int -> Int -> a -> [[a]] -> [[a]]
Next, note that basically the problem can be reduced to modifying the n-th element of an ordinary (non-nested) lists. On the outer list, you modify the y-th sublist, namely, in that sublist you modify the x-th element.
So what does "modifying" mean in Haskell? We can't mutate elements of course2. We need a function that takes a list and returns another one, and does this based on a function which operates on single elements of the list.
modifyNth :: Int -> (a->a) -> [a]->[a]
Observe that this is somewhat similar to the standard function map :: (a->b) -> [a]->[b].
Once you have that function, you can easily implement
modifyXY :: Int -> Int -> (a->a) -> [[a]]->[[a]]
modifyXY x y f nList = modifyNth y (modifyNth x f) nList
(BTW the nList parameter doesn't need to be written, you can η-reduce it).
1As to why this is a good idea: obviously, it allows you to use the function in more general settings. But more importantly, it gives the type checker extra information that you won't do anything with the contained elements themselves. This actually helps to catch a lot of bugs in more complicated applications!
2Actually you can, even with rather nice semantics, in the ST monad.
Let's break this problem into two functions, one that replaces an element in a string with a new char, and one that does this for a list of strings.
I would recommend something like:
replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
here we say that if n is 0, ignore the first element of the string with c, then if n is not 0 and the list has at least one element, prepend that element in front of something (exercise left to reader. Hint: recursion), then if our string is empty, raise an error. I will say that I don't particularly like that error is used here, it would be much better to return a Maybe String, or we could say that replaceCharInStr n c [] = [c]. We could also change the type signature to replaceCharInStr :: Int -> a -> [a] -> [a], since this isn't specific to strings.
For the next function, what we'd like to do is take an index, and apply a function at that index. In general, this function would have type
applyAt :: Int -> (a -> a) -> [a] -> [a]
And could be implemented similarly to replaceCharInStr with
applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
In fact, this is the exact same shape as replaceCharInStr, so if you get this one implemented, then you should be able to implement replaceCharInStr in terms of applyAt as
replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or = applyAt n (const c) xs
Then your replaceChar function could be implemented as
replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or = applyAt n (applyAt m (const c)) strings
All that's left is to implement applyAt.
If you have Edward Kmett's Lens package, then your example is a one-liner:
import Control.Lens
["abc", "def", "ghi"] & ix 1 . ix 2 .~ 'd'
returns
["abc","ded","ghi"]
Lens can emulate the indexing and property access you'd expect from an imperative language, but in Haskell. If you're just beginning to learn Haskell, you should probably wait a bit before using Lens. It's clever and powerful but it's also large and complex.
Try this:
replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
where
replace' 0 c (x:xs) = c : xs
replace' n c (x:xs) = x : (replace' (n-1) c xs)
Here you just traverse the list until the corresponding index is 0 and we replace the character in the matches list. We use the same principle for replacing the charachter in the list. We traverse it and when we reach the specified index, we replace the character at that index by our new one.
In the end, everything gets consed bak on each other to replace the old structure, this time with the character replaced.

Replace an element in a list only once - Haskell

I want to replace an element in a list with a new value only at first time occurrence.
I wrote the code below but using it, all the matched elements will change.
replaceX :: [Int] -> Int -> Int -> [Int]
replaceX items old new = map check items where
check item | item == old = new
| otherwise = item
How can I modify the code so that the changing only happen at first matched item?
Thanks for helping!
The point is that map and f (check in your example) only communicate regarding how to transform individual elements. They don't communicate about how far down the list to transform elements: map always carries on all the way to the end.
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
Let's write a new version of map --- I'll call it mapOnce because I can't think of a better name.
mapOnce :: (a -> Maybe a) -> [a] -> [a]
There are two things to note about this type signature:
Because we may stop applying f part-way down the list, the input list and the output list must have the same type. (With map, because the entire list will always be mapped, the type can change.)
The type of f hasn't changed to a -> a, but to a -> Maybe a.
Nothing will mean "leave this element unchanged, continue down the list"
Just y will mean "change this element, and leave the remaining elements unaltered"
So:
mapOnce _ [] = []
mapOnce f (x:xs) = case f x of
Nothing -> x : mapOnce f xs
Just y -> y : xs
Your example is now:
replaceX :: [Int] -> Int -> Int -> [Int]
replaceX items old new = mapOnce check items where
check item | item == old = Just new
| otherwise = Nothing
You can easily write this as a recursive iteration like so:
rep :: Eq a => [a] -> a -> a -> [a]
rep items old new = rep' items
where rep' (x:xs) | x == old = new : xs
| otherwise = x : rep' xs
rep' [] = []
A direct implementation would be
rep :: Eq a => a -> a -> [a] -> [a]
rep _ _ [] = []
rep a b (x:xs) = if x == a then b:xs else x:rep a b xs
I like list as last argument to do something like
myRep = rep 3 5 . rep 7 8 . rep 9 1
An alternative using the Lens library.
>import Control.Lens
>import Control.Applicative
>_find :: (a -> Bool) -> Simple Traversal [a] a
>_find _ _ [] = pure []
>_find pred f (a:as) = if pred a
> then (: as) <$> f a
> else (a:) <$> (_find pred f as)
This function takes a (a -> Bool) which is a function that should return True on an type 'a' that you wan to modify.
If the first number greater then 5 needs to be doubled then we could write:
>over (_find (>5)) (*2) [4, 5, 3, 2, 20, 0, 8]
[4,5,3,2,40,0,8]
The great thing about lens is that you can combine them together by composing them (.). So if we want to zero the first number <100 in the 2th sub list we could:
>over ((element 1).(_find (<100))) (const 0) [[1,2,99],[101,456,50,80,4],[1,2,3,4]]
[[1,2,99],[101,456,0,80,4],[1,2,3,4]]
To be blunt, I don't like most of the answers so far. dave4420 presents some nice insights on map that I second, but I also don't like his solution.
Why don't I like those answers? Because you should be learning to solve problems like these by breaking them down into smaller problems that can be solved by simpler functions, preferably library functions. In this case, the library is Data.List, and the function is break:
break, applied to a predicate p and a list xs, returns a tuple where first element is longest prefix (possibly empty) of xs of elements that do not satisfy p and second element is the remainder of the list.
Armed with that, we can attack the problem like this:
Split the list into two pieces: all the elements before the first occurence of old, and the rest.
The "rest" list will either be empty, or its first element will be the first occurrence of old. Both of these cases are easy to handle.
So we have this solution:
import Data.List (break)
replaceX :: Eq a => a -> a -> [a] -> [a]
replaceX old new xs = beforeOld ++ replaceFirst oldAndRest
where (beforeOld, oldAndRest) = break (==old) xs
replaceFirst [] = []
replaceFirst (_:rest) = new:rest
Example:
*Main> replaceX 5 7 ([1..7] ++ [1..7])
[1,2,3,4,7,6,7,1,2,3,4,5,6,7]
So my advice to you:
Learn how to import libraries.
Study library documentation and learn standard functions. Data.List is a great place to start.
Try to use those library functions as much as you can.
As a self study exercise, you can pick some of the standard functions from Data.List and write your own versions of them.
When you run into a problem that can't be solved with a combination of library functions, try to invent your own generic function that would be useful.
EDIT: I just realized that break is actually a Prelude function, and doesn't need to be imported. Still, Data.List is one of the best libraries to study.
Maybe not the fastest solution, but easy to understand:
rep xs x y =
let (left, (_ : right)) = break (== x) xs
in left ++ [y] ++ right
[Edit]
As Dave commented, this will fail if x is not in the list. A safe version would be:
rep xs x y =
let (left, right) = break (== x) xs
in left ++ [y] ++ drop 1 right
[Edit]
Arrgh!!!
rep xs x y = left ++ r right where
(left, right) = break (== x) xs
r (_:rs) = y:rs
r [] = []
replaceValue :: Int -> Int -> [Int] -> [Int]
replaceValue a b (x:xs)
|(a == x) = [b] ++ xs
|otherwise = [x] ++ replaceValue a b xs
Here's an imperative way to do it, using State Monad:
import Control.Monad.State
replaceOnce :: Eq a => a -> a -> [a] -> [a]
replaceOnce old new items = flip evalState False $ do
forM items $ \item -> do
replacedBefore <- get
if item == old && not replacedBefore
then do
put True
return new
else
return old