[英]Monad Transformer missing parameter (?)
我有這種類型的別名:
type Board a = ReaderT String (StateT String IO) a
我知道StateT
具有* -> (* -> *) -> * -> *
類型,因此它應該獲得三個參數。 但在上面的示例中, StateT
僅接收String
和IO
-Monad。 現在我想知道缺少的參數傳遞給StateT
的位置。
IO
如此,它應該得到一個參數但沒有得到任何參數。
如果您查看ReaderT
的定義,您會看到它的第二個參數本身應用於它的最后一個參數:
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
^^^
right here
這意味着它的第二個參數m
必須具有種類m:: * -> *
。 如果您只向StateT
應用兩個而不是三個參數,這正是您得到的結果:
StateT :: * -> (* -> *) -> * -> *
StateT x y :: * -> *
(where x :: * and y :: * -> *)
在您的類型Board
中替換ReaderT
的定義時,您將得到:
(1) type Board a = ReaderT String (StateT String IO) a
-- Substituting ReaderT definition (pseudocode)
(2) type Board a = { runReaderT :: String -> StateT String IO a }
^^^^^^^^^^^^^^^^^^
Look, StateT has all its three parameters!
你正確地觀察到
StateT
具有類型* -> (* -> *) -> * -> *
ReaderT
也是如此。
所以它需要 3 個你所說的“參數”。 第一個是*
類型的String
,第三個是*
類型的a
。 而第二個必須是* -> *
。
這在您的示例中由StateT String IO
。 因此,盡管在某種意義上存在StateT
的“缺失參數”,但這需要“缺失”才能獲得某種東西* -> *
- 如果您嘗試了類似type Board a = ReaderT String (StateT String IO Int) a
,這將失敗並出現“種類錯誤”,正是因為ReaderT
的第二個類型參數需要是種類* -> *
,而不是種類*
StateT String IO Int
會擁有。
這同樣適用於為什么IO
使用而不是IO a
形式的東西。 StateT String (IO Int)
不起作用,因為StateT
需要應用於某種類型* -> *
作為其第二類型參數 - IO
具有這種類型,但IO Int
(或任何形式的IO a
)沒有。
退一步說,像ReaderT
和StateT
這樣的 monad 轉換器會轉換另一個 monad,並且 monad 必須始終是* -> *
類型。 IO
是一個 monad, StateT String IO
。 但是IO Int
和StateT String IO Int
不是單子——並不是因為不符合單子法或類似的東西,而是為了更基本的意義,它們是錯誤的類型。 (它們是“具體類型”——具有值的類型——而不是將另一種類型作為參數的“類型構造函數”。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.