2017-10-08 39 views
13

Haskell有在標準庫函數定義FunctorApplicativeMonad實例(具體地,部分應用類型(->) a),圍繞功能組成內置仿/應用性/單子實例。用例用於功能

理解這些實例是一個很好的彎曲練習,但我的問題在於這些實例的實際用途。我很樂意聽到人們使用這些實際代碼的現實場景。

+7

的[讀卡器單子](http://hackage.haskell.org/package/mtl/docs/Control-Monad-Reader.html)基本上是一個NEWTYPE包裝紙圍繞'( - >)'。 – melpomene

+0

我一直都在使用它們。可能你自己不知道:'.'只是'fmap'。 – Bergi

+0

@Bergi:當然,我想這個問題是爲什麼,而不是使用它們只是利用 –

回答

3

有時您想將a -> m b(其中mApplicative)的函數作爲Applicative自己處理。編寫驗證器或解析器時經常發生這種情況。要做到這一點

一種方法是使用Data.Functor.Compose,它寄生在的(->) amApplicative實例給出Applicative實例組成:

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 

還有其他的方法,比如創建自己的NEWTYPE ,或者使用ready-madenewtypes,從基地或其他庫。

7

涉及Functor和Applicative功能實例的常見模式是例如(+) <$> (*2) <*> (subtract 1)。當您必須使用單個值輸入一系列函數時,這非常有用。在這種情況下,上述相當於\x -> (x * 2) + (x - 1)。雖然這非常接近LiftA2,但您可以無限期地擴展此模式。如果你有一個f函數來接受像a -> a -> a -> a -> a -> b這樣的5個參數,你可以像f <$> (+2) <*> (*2) <*> (+1) <*> (subtract 3) <*> (/2)那樣做,並用一個值給它提供。就像在下面的情況一樣;

Prelude> (,,,,) <$> (+2) <*> (*2) <*> (+1) <*> (subtract 3) <*> (/2) $ 10 
(12.0,20.0,11.0,7.0,5.0) 

編輯:信用爲@Will內斯的礦井下的另一個話題評論再評論,來了應用性的功能上一個美麗的使用;

Prelude> let isAscending = and . (zipWith (<=) <*> drop 1) 
Prelude> isAscending [1,2,3,4] 
True 
Prelude> isAscending [1,2,5,4] 
False 
+0

感謝您的意見。所以你發佈的5元組例子。它可以改寫爲((x - >(x + 2,x * 2,x + 1,x-3,x/2))10' - 這裏的應用的優點是不需要重複'x'? –

+0

@Eli Bendersky的主要區別是,在應用形式,如果你知道的主要功能有多少參數需要,整個事情是功能分解(即可以動態撰寫的參數,你喜歡的方式)在lambda形式,你必須同時手邊有一個可靠的lambda函數。 – Redu

+0

你是說我們已經有了一個函數,比如'(,,,,)''而不必手工編寫lambda? –