Reputation: 47
I am pretty new to Haskell. I am trying to write a program that takes two values and a list and replaces every instance of the first value in the list with the second. E.g. repOcc 'n' 'i' "pink"
would return "piik"
.
The following is my code:
repOcc :: t -> t -> [t] -> [t]
repOcc x y (z:zs) = if z == x
then z = y
subst x y zs
else subst x y zs
The error I am receiving at compile time is:
rev.hs:3 :32: error:
parse error on input '='
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
Failed, modules loaded: none.
Upvotes: 1
Views: 3149
Reputation: 477641
Your program looks rather "imperative" whereas Haskell aims to be more "declarative". So you can not set a variable z
in a list: once a list is constructed, you can not alter it anymore. So you have to construct a new list where elements that are equal to x
are set to y
.
Next you make use of the (==)
function. That function is defined in the Eq
typeclass, so you need to add Eq t
as a type constraint to the signature.
So now we can start to construct such function. Usually when working with a list, we make use of recursion. The base case of the recursion is usually the empty list. In case we encounter the empty list, we should return an empty list, regardless what x
and y
are. So we use underscores as "don't care" patterns, and use []
as the list pattern, and write:
repOcc _ _ [] = []
The recursive case is when the list contains a head h
and a tail t
in a (h:t)
pattern. In that case we check whether h
is equal to x
. In case it is, we construct a list with y
as head, otherwise h
is still the head.
repOcc x y (h:t) | x == h = y : tl
| otherwise = h : tl
Now the question remains what the tail of the result list tl
should be. Here we use recursion, so we call repOcc
with x y t
:
where tl = repOcc x y t
Or putting it together:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc _ _ [] = []
repOcc x y (h:t) | x == h = y : tl
| otherwise = h : tl
where tl = repOcc x y t
We can write such recursive functions, but the above is actually a special case of a map
function: we map every character in such way that we check whether it is equal to x
and if it is, we return y
, otherwise we return h
. So we can rewrite the above as:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc x y ls = map (\h -> if h == x then y else h) ls
We can further improve the code by making use of eta-reduction:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc x y = map (\h -> if h == x then y else h)
Upvotes: 5