Haskell has Functor
, Applicative
and Monad
instances defined for functions (specifically the partially applied type (->) a
Sometimes you want to treat functions of the form a -> m b
(where m
is an Applicative
) as Applicative
s themselves. This often happens when writing validators, or parsers.
One way to do this is to use Data.Functor.Compose
, which piggybacks on the Applicative
instances of (->) a
and m
to give an Applicative
instance for the composition:
import Control.Applicative
import Data.Functor.Compose
type Star m a b = Compose ((->) a) m b
readPrompt :: Star IO String Int
readPrompt = Compose $ \prompt -> do
putStrLn $ prompt ++ ":"
readLn
main :: IO ()
main = do
r <- getCompose (liftA2 (,) readPrompt readPrompt) "write number"
print r
There are other ways, like creating your own newtype, or using ready-made newtypes from base or other libraries.