Reputation: 175
Here is an example of what I wanted to do.
let b = ["this","is","a","test!"]
"xx" ++ (b!!3)
This will give me "xxtest!"
Basically if the list contains any string with an exclamation mark then "xx" will be added to this specific string. My questions is how to implement this into a correct function.
Currently I got this
replaceElement [] = []
replaceElement (x:xs) =
if '!' `elem` x
then ["xx"] ++ x : replaceElement xs
else x: replaceElement xs
But this function will just add "xx" into list as an element, it won't be added to the specific string in the list. How can I use "xx" ++ (b!!x) where x is the position of the string with an exclamation mark.
Upvotes: 0
Views: 77
Reputation: 26161
You may also use map
with a helper function like;
addxx :: [String] -> [String]
addxx = map checkBang
where checkBang s | last s == '!' = "xx" ++ s
| otherwise = s
Upvotes: 0
Reputation: 120711
The crucial thing is how ["xx"] ++ x : replaceElement xs
is parsed. This is determined by the fixities of the operators:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :info :
-- ...
infixr 5 :
Prelude> :i ++
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++
So, both :
and ++
are right-associative operators, with the same precedence. Right-associative means, a : b : c
is parsed as a : (b : c)
, instead of (a : b) : c
(as would be the case for left-associative infixl
). Due to the equal precedence, this still holds if you mix :
and ++
, i.s.
["xx"] ++ x : replaceElement xs ≡ ["xx"] ++ (x : replaceElement xs)
IOW, you're just prepending ["xx"]
to the whole result, but the individual elements never get in contact with "xx"
. To achieve that, you need to group "xx"
with x
. The extra brackets are unnecessary then (in fact these could have tipped you off: wrapping "xs"
in an extra layer means you're not working of the string-level anymore as intended, but on the list-of-string level).
A better alternative would of course be to not do any manual recursion: you're simply applying the same operation to all elements of a list; that's what map
is there for:
replaceElement = map $ \x -> if '!'`elem`x
then "xx"++x
else x
Upvotes: 3
Reputation: 34252
The expression
["xx"] ++ x : replaceElement xs
is actually parsed as
["xx"] ++ (x : replaceElement xs)
which does just what you described: inserts "xx"
into the resulting list. What you want to do instead, is:
("xx" ++ x) : replaceElement xs
Upvotes: 4