2017-09-25 28 views
3

我有下面的代碼片段,無法配置它,它是如何工作:類型推斷似乎是一個神奇的

embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int 
embedded = return 1 

它是如何可能只給出一個數字和類型簽名得到這樣回去?編譯器如何做到這一點?

+0

你忘了'return'。'return'是* not *關鍵字:它是一個函數:'return :: Monad m => a - > m a'。 –

+2

你說得對。編譯器不會推斷* this *類型的簽名。它會推斷出更一般的一個。 *你提供了一個不太常用的簽名來告訴編譯器「嘿,我知道我在做什麼,我想要這個」。 –

+0

但是如何成像,它是如何工作的? –

回答

10

措辭的選擇有點不幸。情況並非如此,表述 給出類型簽名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 aMonadmMonad,和return的定義如下:

return = lift . return 

右手returnreturn功能屬於「內」 Monad,而liftMonadTrans和升降機定義基本單數值最高可達MaybeT

這解釋瞭如何創建一個MaybeT價值,但不是整個故事。

在這種情況下,'內部'MonadExceptT String (ReaderT() IO),這是另一個Monad(實際上,另一個MonadTrans)。 return的定義如下:

return a = ExceptT $ return (Right a) 

注意,這是另一個嵌套return,其中右手return屬於另一個嵌套Monad

在這種情況下,嵌套的MonadReaderT() IO - 另一個MonadTrans。它定義return這樣的:

return = lift . return 

又一嵌套return,其中右手returnIO定義(在該特定情況下)return

所有這些都是用a進行參數化,在這種情況下,您已經限制爲Int

所以return 1首先取純值1並將它打包在IO Int。然後將其解壓至ReaderT() IO Int,再次將其打包成ExceptT String (ReaderT() IO) Int。最後,這個值被提升到MaybeT

+0

非常感謝。 –