Я сделал самостоятельный пример из вашего:
{-# 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
Кроме того, в последней строке я поменял аргументы, так как они выглядят в неправильном порядке в вашем примере.Также я улучшил yearDif
определение согласно комментарию @ Реду.
Вот ответы на ваши вопросы.
Вы можете проверить, что аппликативные (и функторные) операциидействительно применяется, следуя рекомендациям Руководства пользователя GHC , а именно, с использованием ключа компилятора -ddump-ds
.Ниже я добавляю еще пару переключателей, чтобы сделать вывод более лаконичным.Я также показываю только выдержку, касающуюся функции maybeAge
.
$ 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)
...
Скорее всего, здесь не будет никакого ускорения.Аппликативные операции для Maybe
имеют постоянную сложность (O(1)
) - точно так же, как монадические.
В оригинальной статье авторы ApplicativeDo
приводят несколько примеров более сложных монадических типов (Haxl
, Data.Seq
, синтаксический анализ и т. Д.), Позволяющих асимптотически более эффективноаппликативные операции.См. Раздел 6 статьи.