Haskell replace an item in a existing list [closed] - haskell

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Im trying to create a function that replace a given existing place with a new place
data Place = Place String Coord [Int]
deriving (Ord,Eq,Show,Read)
data Coord = Cord Double Double
deriving (Ord ,Eq ,Show ,Read)
testData :: [Place]
testData = [ Place "London" (Cord 51.5 (-0.1)) [0, 0, 5, 8, 8, 0, 0],
Place"Cardiff" (Cord 51.5 (-3.2)) [12, 8, 15, 0, 0, 0, 2],
Place"Norwich" (Cord 52.6 (1.3) ) [0, 6, 5, 0, 0, 0, 3],
Place "Birmingham" (Cord 52.5 (-1.9)) [0, 2, 10, 7, 8, 2, 2],
Place"Liverpool" (Cord 53.4 (-3.0)) [8, 16, 20, 3, 4, 9, 2],
Place "Hull" (Cord 53.8 (-0.3)) [0, 6, 5, 0, 0, 0, 4],
Place "Newcastle" (Cord 55.0 (-1.6)) [0, 0, 8, 3, 6, 7, 5],
Place "Belfast" (Cord 54.6 (-5.9)) [10, 18, 14, 0, 6, 5, 2],
Place "Glasgow" (Cord 55.9 (-4.3)) [7, 5, 3, 0, 6, 5, 0],
Place"Plymouth" (Cord 50.4 (-4.1)) [4, 9, 0, 0, 0, 6, 5],
Place "Aberdeen" (Cord 57.1 (-2.1)) [0, 0, 6, 5, 8, 2, 0],
Place "Stornoway" (Cord 58.2 (-6.4)) [15, 6, 15, 0, 0, 4, 2],
Place"Lerwick" (Cord 60.2 (-1.1)) [8, 10, 5, 5, 0, 0, 3],
Place"St Helier" (Cord 49.2 (-2.1)) [0, 0, 0, 0, 6, 10, 0] ]
replaceLocate :: String -> Place -> [Place] -> [Place]
replaceLocate _ _ [] = []
replaceLocate str (Place l d rains) ((Place p c rain):xs)
| str == p = Place l d rains : replaceLocate (Place l d rains) str xs
| otherwise = Place p c rain : replaceLocate (Place l d rains) str xs
while using String to search for the Places that I wanted to change.
But it gives me this error :
Smth.hs:96:22: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the pattern: Place l d rains
In an equation for ‘replaceLocate’:
replaceLocate str (Place l d rains) ((Place p c rain) : xs)
| str == p
= Place l d rains : replaceLocate (Place l d rains) str xs
| otherwise
= Place p c rain : replaceLocate (Place l d rains) str xs
|
96 | replaceLocate str (Place l d rains) ((Place p c rain):xs) | ^^^^^^^^^^^^^^^
Smth.hs:97:16: error:
• Couldn't match type ‘[Char]’ with ‘Place’
Expected type: Place
Actual type: String
• In the second argument of ‘(==)’, namely ‘p’
In the expression: str == p
In a stmt of a pattern guard for
an equation for ‘replaceLocate’:
str == p
|
97 | | str == p = Place l d rains : replaceLocate (Place l d rains) str xs | ^
Smth.hs:97:82: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the second argument of ‘replaceLocate’, namely ‘str’
In the second argument of ‘(:)’, namely
‘replaceLocate (Place l d rains) str xs’
In the expression:
Place l d rains : replaceLocate (Place l d rains) str xs
|
97 | | str == p = Place l d rains : replaceLocate (Place l d rains) str xs | ^^^
Smth.hs:98:86: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the second argument of ‘replaceLocate’, namely ‘str’
In the second argument of ‘(:)’, namely
‘replaceLocate (Place l d rains) str xs’
In the expression:
Place p c rain : replaceLocate (Place l d rains) str xs
|
98 | | otherwise = Place p c rain : replaceLocate (Place l d rains) str xs | ^^^

In your recurve call you are swapping the first two parameters. You need to replace this:
replaceLocate (Place l d rains) str xs
With this:
replaceLocate str (Place l d rains) xs

Related

How to Set Slices in Haskell's HMatrix?

Haskell's HMatrix allows you to conveniently get slices:
m ?? (All, Take 3)
But how can you set slices, especially non-rectangular ones? For instance, in Python's Numpy I'd do:
>>> x = np.arange(12).reshape(3, 4)
>>> x
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x[[0,0], [1,3]] += x[[2,2], [1,3]] # to ix (0, 1) add (2, 1) and to ix (0, 3) add (2, 3)
>>> x
array([[ 0, 10, 2, 14],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
I'm able to write this helper function myself, but, it's sure ugly, and partial, and required I add zipWith3M_ which should exist in the vector library but doesn't:
setSlice :: (Element t, Num t) => Matrix t -> (Extractor, Extractor) -> Vector t -> Matrix t
setSlice parent (Pos (V.map fromIntegral -> irows), Pos (V.map fromIntegral -> icols)) sub = runST $ do
tparent <- thawMatrix parent
zipWith3M_ (writeMatrix tparent) irows icols sub
freezeMatrix tparent

augdentity Haskell Implementation

NOTE: I'm not allowed to use any built-in functions
Given positive ints r and c indicating the number of rows and columns, create a 2D list that represents the "augmented identity matrix" with that dimension: It's the k x k identity matrix (where k = min(r,c)), and augmented rightwards or downwards as needed with zeroes in order to be of size r x c. Stated another way, it's an r x c matrix filled with zeroes that has ones along its main diagonal. I have to write this in both python and Haskell. I wrote the python solution but I'm kinda stuck on Haskell. The Haskell function has to be the following form:
augdentity :: Int -> Int -> [[Int]]
*Homework4> augdentity 3 3
[[1,0,0],[0,1,0],[0,0,1]]
*Homework4> augdentity 3 5
[[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0]]
*Homework4> augdentity 5 3
[[1,0,0],[0,1,0],[0,0,1],[0,0,0],[0,0,0]]
*Homework4> augdentity 2 2
[[1,0],[0,1]]
def augdentity(r,c):
answer = []
for row in range(0, r):
newRow = [0] * c
for col in range(0, c):
if row == col:
newRow[col] = 1
answer.append(newRow)
return answer
So I got this for my haskell function. Put zeros in list when x != y but I don't know how to put 1 when x == y
augdentity :: Int -> Int -> [[Int]]
augdentity x y = [[0 | y <- [1 .. y], x /= y] | x <- [1 .. x]]
How about using if ... then ... else:
augdentity :: Int -> Int -> [[Int]]
augdentity r c = [[ if i == j then 1 else 0 | j <- [1..c] ] | i <- [1..r] ]
main = mapM_ (print . uncurry augdentity) [(3,3),(3,5),(5,3),(2,2)]
-- [[1,0,0],[0,1,0],[0,0,1]]
-- [[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0]]
-- [[1,0,0],[0,1,0],[0,0,1],[0,0,0],[0,0,0]]
-- [[1,0],[0,1]]
Similarly, the python code could be simplified:
def augdentity(rows, cols):
return [[int(i == j) for j in range(cols)] for i in range(rows)]
for dim in [(3,3),(3,5),(5,3),(2,2)]:
print(augdentity(*dim))
# [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
# [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0]]
# [[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0], [0, 0, 0]]
# [[1, 0], [0, 1]]

f string and extended unpacking

I am trying to do extended unpacking of tuple with * syntax. I'm trying to format string with f'' string syntax. None of those work in visual-studio-code python3.7.3 linuxmint64 system.
l = [1, 2, 3, 4, 5, 6]
a, *b = l
print(a, b)
Here is the error :
line 3
a, *b = l
^
SyntaxError: invalid syntax
Your Code:
l = [1, 2, 3, 4, 5, 6]
a, *b = l
print(a, b)
The above code won't as the correct syntax is b=[*l]. The * is used to unpack a list.
So if you want to have some values in both a and b so the code below...
l = [1, 2, 3, 4, 5, 6]
d = [3,2,1]
a , b = [*l] , [*d] # Here [*l] unpacks l in a list and assign it to a and
# and [*d] unpacks d in a list and assign it to b
print(a , b)
Hope this helps...

Pattern matching a List of Strings with a String using isInfixOf

Hello i am a beginner in haskell and i have a problem with comparing/matching Strings from a set List with a given String as Parameter.
What i want to achieve is:
I have a set List
colorTypes = ["red" , "blue" ,"yellow" , "green" ]
what i want to do is make a Function to compare each element of the List with a given String using the isInfixOf Function from Data.List and depending on the outcome from isInfixOf return a Pattern
Example if i use the function:
getColorData colorTypes "red"
it should return
[1, 0, 0, 0]
What i have tried is:
import Data.List
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
i get the error : Parse error in pattern: isInfixOf with this function
i also tried this with case
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str = case (g:h:j:k) of
isInfixOf g str -> [1, 0, 0, 0]
isInfixOf h str -> [0, 1, 0, 0]
isInfixOf j str -> [0, 0, 1, 0]
isInfixOf k str -> [0, 0, 0, 1]
this also doesnt work and i get the Couldn't match type error.
I don't know if my approach is wrong or if there are any other ways to get what i want but i appreciate any help
The problem is here that you pattern match with:
getColorData (g:h:j:k) str
Here g, h, and j are the heads (first elements) of the list, but k is the tail of the list (the remaining items). So k has as type [String], not String.
We can fix it by using [g,h,j,k] which is a list of four elements:
getColorData :: [String] -> String -> [Int]
getColorData [g,h,j,k] str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
But still it is not really good design. Since for lists with less, or more than four elements, this function will error. I'm also not sure whether using an isInfixOf condition is a good idea at all: it means that the order of the list can sometimes determine what the result will be: a list where two elements are swapped might result in a different. Finally the code is very repetitive (not following the Don't Repeat Yourself principle).
A more elegant version could be:
getColorData :: Eq a => [a] -> [a] -> Maybe [Int]
getColorData [] _ = Nothing
getColorData (x:xs) s | isInfixOf x s = Just (1: map (const 0) xs)
| otherwise = fmap (0:) (getColorData xs s)
Here we let it work for any type a where two as have an equality relation. Furthermore it works with lists of all lengths. It returns Nothing if the elements can not be found, and Just e with e an entity vector with the length of the list as the number of dimensions.

How to build diagonal matrix with list comprehension

How can I build an infinite matrix with numbers placed in it diagonally with list comprehension?
[[ 1, 2, 4, 7, 11, ...],
[ 3, 5, 8, 12, 17, ...],
[ 6, 9, 13, 18, 24, ...],
[10, 14, 19, 25, 32, ...],
...]
I've tried to do it like this:
firstColumn = take 6 $ map fst $ iterate (\(a,b) -> (a+b,b+1)) (1,2)
matr :: [[Int]]
matr = [take 6 $ map fst $ iterate (\(x,y) -> (x+y, y+1)) (a, i) | a <- firstColumn, let i = 1]
But how can I pass (i + 1) to next every row (in other words, how do I iterate for additional rows)
By finding a formula for the x and y indices, f.e.:
[[ 1 + (x + y) * (x + y + 1) `div` 2 + y | x <- [0..]] | y <- [0..]]

Resources