简体   繁体   中英

ApplicativeDo pragma and Applicative Functor in Haskell

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:

  1. How can I check does maybeAge use Applicative Functor semantic or Monad one in this case?
  2. What is an advantage in that case if Applicative Functor used?

About: ApplicativeDo .

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.

  1. 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) ... 
  2. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM