Andi Pavllo
Andi Pavllo

Reputation: 2506

Haskell, print modified list values with map

I have written the following code, which should take a list of values and print only the values > average, modifying them as val - avg. For example printModVal [9,0,6] should print 4 1, one element per line, using System.IO print function.

import Data.List
import System.IO

printModVal :: [Float] -> IO ()
printModVal xs = ???
  where
    average = (foldr (+) 0 xs) / genericLength xs
    --use map here and print the values > average as value-average


modVal :: Float -> Float -> Float
modVal x y = x - y


mapVal  :: (a->b) -> [a] -> [b]
mapVal f [] =  []
mapVal f (x:xs) =  f x : mapVal f xs

I would like to know how, at this point, how can I use mapVal (with modVal as mapping function) inside the function printModVal, in order to print the values > 0 (once modified by the mapping function). Thank you.

Upvotes: 0

Views: 171

Answers (1)

Marvin Sielenkemper
Marvin Sielenkemper

Reputation: 820

You have to apply a filter.

Either to the resulting list

printModVal xs = mapM_ print $ filter (> 0) (mapVal (\x -> modVal x average) xs)
  where
    average = (foldr (+) 0 xs) / genericLength xs

or to the incoming list

printModVal xs = mapM_ print $ mapVal (\x -> modVal x average) (filter (> average) xs)
  where
    average = (foldr (+) 0 xs) / genericLength xs

map does never change the length of the list it processes. Any function with the signature (a->b)->[a]->[b] is very limited in what it can do due to parametricity.

Upvotes: 3

Related Questions