Reputation: 541
An example from Functor, Applicative, and Monad slightly changed:
{-# LANGUAGE ApplicativeDo #-}
import Safe (readMay)
-- import Control.Applicative ((<$>), (<*>))
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
maybeAge fS bS = do
fI <- readMay fS
bI <- readMay bS
pure $ yearDiff fI bI
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
displayAge $ maybeAge birthYearString futureYearString
where maybeAge
with do
I used instead of
maybeAge fS bS = yearDiff <$> readMay fS <*> readMay bS
I have the 2 questions:
maybeAge
use Applicative Functor semantic or Monad one in this case?About: ApplicativeDo.
Upvotes: 1
Views: 168
Reputation: 2578
I made a self-contained example out of yours:
{-# LANGUAGE ApplicativeDo #-}
import Text.Read (readMaybe)
displayAge :: Maybe Int -> IO ()
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff :: Int -> Int -> Int
yearDiff = (-)
maybeAge :: String -> String -> Maybe Int
maybeAge fS bS = do
fI <- readMaybe fS
bI <- readMaybe bS
pure $ yearDiff fI bI
main :: IO ()
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
displayAge $ maybeAge futureYearString birthYearString
Also, in the last line, I swapped the arguments, as they appear to be in the wrong order in your example. Also I improved yearDif
definition as per @Redu's comment.
Here are the answers on your questions.
You can check that applicative (and functor) operations are indeed applied, following the advice in the GHC's User Guide, namely, using the -ddump-ds
compiler switch. I add a couple more switches below to make the output more succinct. I also show only excerpt concerning the maybeAge
function.
$ ghc appdo.hs -ddump-ds -dsuppress-type-applications -dsuppress-module-prefixes
[1 of 1] Compiling Main ( appdo.hs, appdo.o )
==================== Desugar (after optimization) ====================
Result size of Desugar (after optimization)
= {terms: 75, types: 75, coercions: 0, joins: 0/0}
...
-- RHS size: {terms: 17, types: 13, coercions: 0, joins: 0/0}
maybeAge :: String -> String -> Maybe Int
[LclId]
maybeAge
= \ (fS_a1h3 :: String) (bS_a1h4 :: String) ->
<*>
$fApplicativeMaybe
(fmap
$fFunctorMaybe
(\ (fI_a1h5 :: Int) (bI_a1h6 :: Int) -> yearDiff fI_a1h5 bI_a1h6)
(readMaybe $fReadInt fS_a1h3))
(readMaybe $fReadInt bS_a1h4)
...
Most certainly, no speedup is gained here. Applicative opertaions for Maybe
have constant complexity (O(1)
) — just like the monadic ones.
In the original paper, the authors of ApplicativeDo
give several examples of more sophisticated monadic types (Haxl
, Data.Seq
, parsing, etc.) allowing for asymptotically more efficient applicative operations. See Section 6 of the paper.
Upvotes: 2