2013-05-15 104 views
3

這幾個問題集於一身:類型和做記號

  1. do符號,並每行必須返還相同種類?例如,我可以在單個do塊中寫入一行,該塊返回一個IO monad,另一行返回一個整數? (我的理解的基礎上,脫糖與>>>>=如何似乎工作,是,答案是否定的。)

  2. 如果沒有,那麼編譯器如何確定哪些類型的線必須全部回報?在我見過的所有例子中,作者都​​認爲我們只是與IO monads合作。但你怎麼知道,對於給定的do塊,每行必須返回什麼?

  3. 再次假定#1的答案是否定的:如何使用在do塊內不返回正確類型的monad的函數?例如,考慮這個的WebSockets代碼:

    application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00() 
    application state rq = do 
        WS.acceptRequest rq 
        msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text 
        return() 
    

    假設我要打印的msg值。我怎樣才能以與do區塊的類型不衝突的方式去做?

+0

你爲什麼不試試呢?此外,由於符號只是語法糖(正如您所說,它轉化爲「(>> =)」和「(>>)」),因此手頭的機制與任何其他類型的機制完全相同,而不是具體到do-notation和'Monad's。 – chris

+0

對不起,我無意中弄亂了我上次編輯的代碼格式(引入了枚舉)。不幸的是,我的更正將會有太少的字符被允許作爲編輯。你能再補救一下嗎? – chris

+0

是的,我修好了。我看你是如何試圖使用Markdown編號列表的,但它們似乎與代碼塊有衝突。這就是爲什麼我選擇將每個數字放在自己的段落中。 – rlkw1024

回答

8
  1. 在一個做塊,每行可以返回不同的類型,但它們必須在相同的單子
    • 一個線可以返回一個IO String和一個可以返回一個IO Integer但它們都具有爲IO
  2. 與Haskell的其餘部分相同。類型推斷。就像在Haskell的其他部分一樣,它並不總是能夠工作,而當它沒有時,你也必須註釋它。
  3. 這樣做有
    • let的2種方式,記得在GHCI必須使用讓聲明局部變量,你可以做同樣的do塊。 let someMonad = doSomething
      • 通知,沒有in
    • Monad的變形金剛!這是一個很大的話題,可以在blurb中解釋,但基本上它們是具有特殊功能的monad,它可以將另一個monad「提升」到變壓器中。變形金剛通常以T結尾,例如StateT。幾乎每個你使用的monad都有一個等效的變壓器。
4

要回答你的最後一個問題的最後一部分,

假設我要打印的msg值。我怎樣才能以與do區塊的類型不衝突的方式去做?

由於jozefg said in his answer,monad變壓器通常是您需要的。但是,在這種情況下,WebSockets p monad不是變壓器。但是,它是MonadIO的一個實例,它是monad堆棧的一個類,它具有IO「底部」,因此可讓您從其中運行任意的IO操作。

MonadIO類提供了有型

liftIO :: MonadIO m => IO a -> m a 

在你的情況下,功能liftIO,這成爲IO a -> WebSockets Hybi00 a,所以你可以用它來print msg行動從IO()轉換爲WebSockets Hybi00(),然後你就可以使用在do區塊中:

application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00() 
application state rq = do 
    WS.acceptRequest rq 
    msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text 
    liftIO $ print msg