I want to write a function very similar to filter using the odd function that takes a list and returns that list with any odd numbers squared.

ex

gchi> sqrodd [1,2,3,4,5]
[1,2,9,4,25]

what I have and believe is close is

sqrodd :: (a->Bool) -> [a] -> [a]
sqrodd odd []     = []
sqrodd odd (x:xs) = if odd x
                    then (x*x) :sqrodd odd xs
                    else x : sqrodd odd xs

but I get errors with the function definition saying "couldn't match expected type a -> Bool with actual type [a]"

Cactus's user avatar

Cactus

27.8k10 gold badges74 silver badges165 bronze badges

asked Sep 13, 2016 at 4:05

user47835's user avatar

Your sqrodd function has two parameters: the first is an oddness-predicate a -> Bool and the second is a list of elements [a]. In your example usage, you pass [1..5] as the first argument, in place of the a -> Bool predicate.

However, what you really want is to not have two parameters, i.e. change sqrodd to a single-parameter function sqrodd :: [a] -> [a] and just use the function odd from the Prelude.

Note that you'll still need to be a bit more restrictive in your sqrodd type because it is not true that you can apply odd or (*) on elements of any type a; you may want to read up on typeclasses once you get there to get over that next hurdle.

answered Sep 13, 2016 at 4:11

Cactus's user avatar

Comments

As you wrote yourself, you want a function that takes a list as argument and returns another list, so instead of having type signature

    sqrodd :: (a->Bool) -> [a] -> [a]

You should make a function with a type signature that looks like this

    sqrodd :: [a] -> [a]

which is exactly what you have written on the beginning. Because of that compiler expects, that the first argument of this function will be a function of (a -> bool). You should remove odd from arguments list and change type signature as shown above. This will cause the function to use odd from prelude instead of expecting filter function as argument.

Another way of doing it, is renaming you function as, for example sqrfiltered and then you can define sqrodd as partially applied sqrfiltered

    sqrodd = sqrfiltered odd

Not tested, but it should be right.

answered Sep 13, 2016 at 8:09

Antisthenes's user avatar

Comments

The filter function examines each element in a list and returns a new list that only contains the elements satisfying the condition.

But what you want to accomplish is to transform a list to a new list; the new list has the same number of elements of the old one. You're not filtering out anything; you're mapping elements from one list to another according to some rules.

Here are two possible ways to write your function.

oddSquared, oddSquared' :: [Int] -> [Int]

oddSquared l = [ if (x `mod` 2 /= 0) then x^2 else x | x <- l ]

oddSquared'  = map (\x -> if odd x then x^2 else x)

answered Sep 13, 2016 at 13:38

ƛƛƛ's user avatar

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.