0

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.

3 Answers 3

4

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
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.