我有下面的代碼片段,無法配置它,它是如何工作:類型推斷似乎是一個神奇的
embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int
embedded = return 1
它是如何可能只給出一個數字和類型簽名得到這樣回去?編譯器如何做到這一點?
我有下面的代碼片段,無法配置它,它是如何工作:類型推斷似乎是一個神奇的
embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int
embedded = return 1
它是如何可能只給出一個數字和類型簽名得到這樣回去?編譯器如何做到這一點?
措辭的選擇有點不幸。情況並非如此,表述 給出類型簽名MaybeT (ExceptT String (ReaderT() IO)) Int
。
As n.m.寫的評論,如果你不提供一個類型,表達的是更普遍:
Prelude> embedded = return 1
Prelude> :type embedded
embedded :: (Num a, Monad m) => m a
通過與類型註釋,可以明確您要高於一般的少一些。
具體來說,你聲明你想要的類型是MaybeT (ExceptT String (ReaderT() IO)) Int
。
return
如何工作? MaybeT m a
是Monad
當m
是Monad
,和return
的定義如下:
return = lift . return
右手return
是return
功能屬於「內」 Monad
,而lift
由MonadTrans
和升降機定義基本單數值最高可達MaybeT
。
這解釋瞭如何創建一個MaybeT
價值,但不是整個故事。
在這種情況下,'內部'Monad
是ExceptT String (ReaderT() IO)
,這是另一個Monad
(實際上,另一個MonadTrans
)。 return
的定義如下:
return a = ExceptT $ return (Right a)
注意,這是另一個嵌套return
,其中右手return
屬於另一個嵌套Monad
。
在這種情況下,嵌套的Monad
是ReaderT() IO
- 另一個MonadTrans
。它定義return
這樣的:
return = lift . return
又一嵌套return
,其中右手return
爲IO
定義(在該特定情況下)return
。
所有這些都是用a
進行參數化,在這種情況下,您已經限制爲Int
。
所以return 1
首先取純值1
並將它打包在IO Int
。然後將其解壓至ReaderT() IO Int
,再次將其打包成ExceptT String (ReaderT() IO) Int
。最後,這個值被提升到MaybeT
。
非常感謝。 –
你忘了'return'。'return'是* not *關鍵字:它是一個函數:'return :: Monad m => a - > m a'。 –
你說得對。編譯器不會推斷* this *類型的簽名。它會推斷出更一般的一個。 *你提供了一個不太常用的簽名來告訴編譯器「嘿,我知道我在做什麼,我想要這個」。 –
但是如何成像,它是如何工作的? –