newtype FlippedIO a = MkFlippedIO { runFlippedIO :: IO a }
deriving Functor
instance Applicative FlippedIO where
pure = MkFlippedIO . pure
liftA2 f (MkFlippedIO x) (MkFlippedIO y) =
MkFlippedIO ((flip . liftA2 . flip) f x y)
data Person = Person String String
deriving Show
putStrLnFlipped = MkFlippedIO . putStrLn
getLineFlipped = MkFlippedIO getLine
getPerson :: IO Person
getPerson = runFlippedIO $
Person
<$> (putStrLnFlipped "Enter your first name:" *> getLineFlipped)
<*> (putStrLnFlipped "Enter your last name:" *> getLineFlipped)
It runs things "backwards":
ghci> getPerson
One
Enter your last name:
Two
Enter your first name:
Person "Two" "One"