https://hackage.haskell.org/package/transformers-0.6.0.2/docs/src/Control.Monad.Trans.Reader.html#ReaderT
我發現這Reader是基于ReaderTusing實作的Identity。為什么不Reader先制作再制作ReaderT?有具體的理由來實施這種方式嗎?
uj5u.com熱心網友回復:
它們是相同的資料型別,可以在Reader和之間共享盡可能多的代碼ReaderT。就目前而言,只有runReader,mapReader和withReader有任何特殊情況。并且withReader沒有任何唯一代碼,它只是一種型別特化,因此實際上只有兩個函式Reader對ReaderT.
您可能會查看模塊匯出并認為購買不多,但實際上確實如此。有很多的定義實體ReaderT是Reader自動具有為好,因為它是同一型別。因此,對于這兩種型別只有一個基礎型別實際上是相當少的代碼。
鑒于此,您的問題歸結為詢問為什么Reader在 之上實施ReaderT,而不是相反。為此,嗯,這只是唯一可行的方法。
讓我們試著去另一個方向,看看哪里出了問題。
newtype Reader r a = Reader (r -> a)
type ReaderT r m a = Reader r (m a)
是的,好的。行內別名并去掉 newtype 包裝,它應該ReaderT r m a是等效的r -> m a。現在讓我們轉到Functor實體:
instance Functor (Reader r) where
fmap f (Reader g) = Reader (f . g)
是的,這是該Functor定義的唯一可能實體Reader。并且由于ReaderT是相同的底層型別,它還提供了一個Functorfor的實體ReaderT。除非發生了可怕的錯誤。如果您將第二個引數和結果型別修復為您所期望的,則fmap專門針對 type (m a -> m b) -> ReaderT r m a -> ReaderT r m b。這根本不對。fmap的第一個引數應該是型別(a -> b)。這m兩側偷偷溜進去肯定是不對的。
但這只是當您嘗試ReaderT根據Reader而不是相反的方式實作時發生的情況。為了Functor在兩種型別之間共享(以及更多)代碼,每種型別中的最后一個型別變數必須與底層型別中的相同。而這時候基礎只是不可能ReaderT的Reader。它必須引入一個額外型別的變數,并做到這一點的唯一方法,而獲得做完所有的換人正確的結果是使得a在Reader r a指除不同的東西a在ReaderT r m a。這與Functor在兩種型別之間共享更高種類的實體是不兼容的。
有趣的是,您選擇了最好的情況,Reader因為它可以讓型別完全對齊。例如,如果您嘗試StateT基于State,事情會失敗得更快。甚至沒有辦法撰寫一個型別別名來添加m引數并擴展為該對的正確內容。Reader需要您在事情崩潰之前進一步探索。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/408314.html
標籤:
上一篇:在haskell中使用BST的集合上的交集和差分函式
下一篇:如何使用鍵的值組合字典串列?
