Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Haskell: Change the (n,m)th element in a Lists in List

The replaceAtMatrix function should take in a tuple (Int,Int) that decides what position is the value that needs to be changed, a value to be changed to, and the List in List [[a]].

If the tuple’s values exceed the lists length the original [[a]] needs to be returned.

replaceAtList :: Int -> a -> [a] -> [a] 
replaceAtList _ _ [] = []
replaceAtList 0 a (_:xs) = a:xs
replaceAtList number a (x:xs)
    | number < 0 = x:xs
    | number > (length (x:xs)-1) = x:xs 
    | otherwise = x : replaceAtList (number-1) a xs

replaceAtMatrix :: (Int,Int) -> a -> [[a]] -> [[a]]
replaceAtMatrix _ _ [] = []
replaceAtMatrix (0,num2) a (x:xs) = replaceAtList num2 a x : xs
replaceAtMatrix (num1,num2) a (x:xs)
    | num1 < 0 = x:xs
    | num1 > (length (x:xs)-1) = x:xs
    | num2 < 0 = x:xs
    | num2 > (length (x:xs)-1) = x:xs 
    | otherwise = x : replaceAtMatrix (num1-1,num2) a xs

There are test for which I checked, and it passes most of them, but there’s one where it goes in an infinite cycle. Here’s the tests that work.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

replaceAtMatrix (-1,0) 'A' ["bcd","lds","rtz"] == ["bcd","lds","rtz"]
replaceAtMatrix (0,0) 'A' ["bcd","lds","rtz"] == ["Acd","lds","rtz"]
replaceAtMatrix (2,0) 'A' ["bcd","lds","rtz"] == ["bcd","lds","Atz"]
replaceAtMatrix (3,0) 'A' ["bcd","lds","rtz"] == ["bcd","lds","rtz"]
replaceAtMatrix (2,2) 'A' ["bcd","lds","rtz"] == ["bcd","lds","rtA"]

And here’s the one that doesn’t.

Edit: I just realized it’s probaly beacuse I use length on an infinite list. How can I rewrite it without using length?

take 5 (replaceAtMatrix (1,2) 100 [[1..],[1,11..],[],[12,13,14]] !! 1) == [1,11,100,31,41]

Without the guard, I get a variable not in scope error.

replaceAtList :: Int -> a -> [a] -> [a] 
replaceAtList _ _ [] = []
replaceAtList 0 a (_:xs) = a:xs
replaceAtList number a (x:xs) = x : replaceAtList (number-1) a xs

replaceAtMatrix :: (Int,Int) -> a -> [[a]] -> [[a]]
replaceAtMatrix _ _ [] = []
replaceAtMatrix (0,num2) a (x:xs) = replaceAtList num2 a x : xs
replaceAtMatrix (num1,num2) a (x:xs) = x : replaceAtMatrix (num1-1,num2) a xs

>Solution :

Don’t use length. This will error on infinite lists: you do not need this: in case the number > length somelist, eventually it will reach the end of the list:

replaceAtList :: Int -> a -> [a] -> [a] 
replaceAtList _ _ [] = []
replaceAtList n _ xs
    | n < 0 = xs
replaceAtList 0 a (_:xs) = a:xs
replaceAtList number a (x:xs) = x : replaceAtList (number-1) a xs

replaceAtMatrix :: (Int,Int) -> a -> [[a]] -> [[a]]
replaceAtMatrix _ _ [] = []
replaceAtMatrix (m, _) _ xs
    | m < 0 = xs
replaceAtMatrix (0,num2) a (x:xs) = replaceAtList num2 a x : xs
replaceAtMatrix (num1,num2) a (x:xs) = x : replaceAtMatrix (num1-1,num2) a xs
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading