[英]Compose IO Operations
嗨,我正在嘗試編寫一些 IO 包裝函數。
我當前的代碼(有效)是:
getUserHome :: IO String
getUserHome = do
usr_id <- getRealUserID
homeDirectory <$> getUserEntryForID usr_id
我正在尋找的是一種更方便的表示法(不使用do
-keyword 的表示法)。
沒有任何單子沙拉,我只會寫
getUserHome = homeDirectory . getUserEntryForID . getRealUserID
我猜有一個替代運算符用於.
尊重Monad..? 但在我所有的搜索中,我還沒有找到它。
我試過<$>
但這似乎不是我想要的:
src/Main.hs:49:21: error:
• Couldn't match type ‘IO UserEntry’ with ‘UserEntry’
Expected type: UserID -> UserEntry
Actual type: UserID -> IO UserEntry
• In the second argument of ‘(<$>)’, namely ‘getUserEntryForID’
In the first argument of ‘(<$>)’, namely
‘homeDirectory <$> getUserEntryForID’
In the expression:
homeDirectory <$> getUserEntryForID <$> getRealUserID
|
49 | homeDirectory <$> getUserEntryForID <$> getRealUserID -- usr_id
謝謝你的幫助^^
您可以使用>>=
,因為 Haskell 最終“脫糖”了do
塊:
getUserHome :: IO String
getUserHome = getRealUserID >>= \usr_id -> homeDirectory <$> getUserEntryForID usr_id
這可以簡化為:
getUserHome :: IO String
getUserHome = getRealUserID >>= fmap homeDirectory . getUserEntryForID
或者:
getUserHome :: IO String
getUserHome = getRealUserID >>= (homeDirectory <$>) . getUserEntryForID
首先始終考慮類型:
getRealUserID :: IO UserId
getUserEntryForID :: UserId -> IO UserEntry
homeDirectory :: UserEntry -> String
現在你可以:
應用getRealUserID
和getUserEntryForID
。 這直接適合
(>>=):: ma -> (a -> mb ) -> mb (>>=):: IO UserId -> (UserId -> IO UserEntry) -> IO UserEntry
實際上,如果您希望它看起來像合成鏈,我更喜歡翻轉版本,即
getUserEntryForID =<< getRealUserID:: IO UserEntry
將homeDirectory
應用於此。 在您的情況下,這根本不是一元的,因此您需要使用fmap
或<$>
來解除它。 考慮運算符優先級。
fmap homeDirectory $ getUserEntryForID =<< getRealUserID homeDirectory <$> (getUserEntryForID =<< getRealUserID)
因為 monad 是關聯的,所以你也可以反過來做:
使用getUserEntryForID
編寫homeDirectory
。 后者已經是標准的Kleisli 箭頭,您也可以將homeDirectory
提升到 Kleisli 以使用 Kleisli 組合運算符:
pure. homeDirectory:: UserEntry -> IO String pure. homeDirectory <=< getUserEntryForID:: UserId -> IO String
再次將整個內容應用於getRealUserID
:
(pure. homeDirectory <=< getUserEntryForID) =<< getRealUserID
事實上,您也可以使用 dummy ()
參數將getRealUserID
轉換為 Kleisli 箭頭。 這種風格在 Haskell 中相當少見,但它的優點是 Kleisli 組合的關聯性變得明顯,就像正常的 function 組合一樣明顯:
pure . homeDirectory <=< getUserEntryForID <=< const getRealUserID $ ()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.