For the sake of good order, I am posting the different solutions as per Daniel Fischer's suggestions in a tested module: <TestIO.hs> module TestIO where import Control.Monad data Person = Person {name :: String, age :: Int} deriving Show -- operator version of apply infix 0 |> (|>) :: a -> (a -> b) -> b x |> f = f x -- verbal version of (|>) operator apply :: a -> (a -> b) -> b apply x f = f x setName :: String -> Person -> IO Person setName s p = do putStrLn "setting name" return p {name=s} setAge :: Int -> Person -> IO Person setAge i p = do putStrLn "setting age" return p {age=i} -- first way: using recursion update :: [Person -> IO Person] -> Person -> IO Person update [] p = return p update (f:fs) p = do p' <- f p update fs p' -- second way: using foldm and (|>) operator update1 :: [Person -> IO Person] -> Person -> IO Person update1 fs p = foldM (|>) p fs -- third way: (|>) is now function apply update2 :: [Person -> IO Person] -> Person -> IO Person update2 fs p = foldM apply p fs p1 = Person {name="alia", age=12} p2 = update [(setName "sam"), (setAge 32)] p1 p3 = update1 [(setName "sue"), (setAge 40)] p1 p4 = update2 [(setName "jo"), (setAge 55)] p1 </TestIO.hs>