[英]How do you use Control.Applicative to write cleaner Haskell?
在最近的一個風格問題的答案中 ,我寫道
main = untilM (isCorrect 42) (read `liftM` getLine)
和
isCorrect num guess =
case compare num guess of
EQ -> putStrLn "You Win!" >> return True
...
Martijn幫助提出了替代方案:
main = untilM (isCorrect 42) (read <$> getLine)
EQ -> True <$ putStrLn "You Win!"
使用Control.Applicative中的抽象可以使Haskell代碼中的哪些常見模式更清晰? 有效使用Control.Applicative時要記住哪些有用的經驗法則?
回答你的問題有很多話要說,但是,既然你問過,我會提供這個“經驗法則”。
如果您正在使用do
-notation,並且您正在排序的表達式[2]中未使用生成的值[1],那么該代碼可以轉換為Applicative樣式。 同樣,如果在排序的表達式中使用一個或多個生成的值,則必須使用Monad
而Applicative
不足以實現相同的代碼。
例如,讓我們看看以下代碼:
do a <- e1
b <- e2
c <- e3
return (f a b c)
我們看到<-
沒有任何表達式出現任何生成的值( a
, b
, c
)。 因此,我們可以將其轉換為使用Applicative代碼。 這是一個可能的轉變:
f <$> e1 <*> e2 <*> e3
另一個:
liftA3 f e1 e2 e3
另一方面,以這段代碼為例:
do a <- e1
b <- e2 a
c <- e3
return (f b c)
此代碼不能使用Applicative
[3],因為稍后在理解中的表達式中使用生成的值a
。 這必須使用Monad
來達到其結果 - 嘗試將其納入Applicative
以了解原因。
有關於這個問題的另外一些有趣和有用的信息,但是,我只打算給你這個經驗法則,讓你可以掠過do
-comprehension並很快確定它是否可以被分解成Applicative
樣式代碼。
[1]出現在左邊的那些<-
。
[2]表達式出現在<-
的右側。
[3]嚴格來說,部分內容可以通過分解e2 a
。
基本上,monad也是應用函子[1]。 因此,每當您發現自己使用liftM
, liftM2
等時,您可以使用<*>
將計算鏈接在一起。 從某種意義上說,你可以認為applicative functor與函數類似。 可以通過執行f <$> x <*> y <*> z
來提升純函數f
。
與monad相比,applicative functor無法有選擇地運行其參數。 所有論點的副作用都將發生。
import Control.Applicative
ifte condition trueClause falseClause = do
c <- condition
if c then trueClause else falseClause
x = ifte (return True) (putStrLn "True") (putStrLn "False")
ifte' condition trueClause falseClause =
if condition then trueClause else falseClause
y = ifte' <$> (pure True) <*> (putStrLn "True") <*> (putStrLn "False")
x
僅輸出True
,而y
依次輸出True
和False
。
[1] Typeclassopedia 。 強烈推薦。
[2] http://www.soi.city.ac.uk/~ross/papers/Applicative.html 。 雖然這是一篇學術論文,但並不難理解。
[3] http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors 。 很好地解釋了這筆交易。
[4] http://book.realworldhaskell.org/read/using-parsec.html#id652399 。 顯示monadic Parsec
庫如何以應用方式使用。
請參閱Bryan O'Sullivan的實際工作,了解應用仿函數的基礎知識 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.