2015-09-11 81 views
3

我讀Dynamic programming example,有這樣的代碼:警衛在哈斯克爾

buy n = r!n 
    where r = listArray (0,n) (Just (0,0,0) : map f [1..n]) 
      f i = do (x,y,z) <- attempt (i-6) 
        return (x+1,y,z) 
       `mplus` 
       do (x,y,z) <- attempt (i-9) 
        return (x,y+1,z) 
       `mplus` 
       do (x,y,z) <- attempt (i-20) 
        return (x,y,z+1) 
      attempt x = guard (x>=0) >> r!x 

我的問題是如何attempt x = guard (x>=0) >> r!x作品?

根據該Control.Monad源代碼,

guard True  = pure() 
guard False  = empty 

pure :: a -> f a 

m >> k = m >>= \_ -> k 

所以如果x> 0,則:

attempt x 
    = (guard True) >> (r!x) = (pure()) >> (r!x) 
    = (pure()) >>= \_ -> r!x = (f()) >>= (\_ -> r!x) 

因此f()應(在這種情況下Maybe a)是m a類型,但如何做Haskell知道什麼f是?因爲它從未被指定,所以f()可以返回empty。 (ff指在純)

如果x < 0,empty不在Maybe,如何能這仍然施加到>>=

+0

'純()::也許(==剛()'? – Mephy

+0

@Mephy'Maybe()== Just()'如何應用於'>> ='? – CYC

+1

在[this source](http://hackage.haskell.org/package/base-4.8)的第634行中沒有應用程序,'pure():: Maybe()'被定義爲'Just() .1.0 /文檔/ SRC/GHC.Base.html)。 – Mephy

回答

2

在您手動評估attempt x的最後一個表達式中,您正在混合類型和值。 pure :: a -> f a不是定義;它是一個類型簽名(請注意::)。要充分引用它的類型的pure是:

GHCi> :t pure 
pure :: Applicative f => a -> f a 

這裏,f代表的Applicative任何情況下,與a任何類型。在你的情況下,你正在使用單粒子/應用函子Maybe,所以fMaybepure()的類型是Maybe()。 (() ::()是對結果不感興趣時​​使用的虛擬值。()pure()是一個值,但()Maybe()是一種類型 - 值爲()的類型)。

我們將繼續從您評價的最後一步正確:

(pure()) >>= \_ -> r!x 

如何哈斯克爾知道什麼[pure()]是什麼?

在某種意義上說,它並不需要。這使得pure()使用此功能是(>>=)。它有以下類型:

GHCi> :t (>>=) 
(>>=) :: Monad m => m a -> (a -> m b) -> m b 

設置mMaybe,在你的情況,我們得到:

Maybe a -> (a -> Maybe b) -> Maybe b 

類型的第一個參數是Maybe a,所以(>>=)能夠處理任何Maybe a值,包括pure(),無論它是否是一個Just -something或Nothing。當然,它會處理JustNothing不同,因爲這是the Monad instance整點:

(Just x) >>= k  = k x 
Nothing >>= _  = Nothing 

我們還是要完成評估。要做到這一點,我們需要知道pure如何爲Maybe定義。我們可以發現在the Applicative instance of Maybe定義:

pure = Just 

現在,我們終於可以繼續:)

(pure()) >>= \_ -> r!x 
Just() >>= \_ -> r!x 
(\_ -> r!x)() -- See the implementation of `(>>=)` above. 
r!x 
3

這是多個問題之一,但讓我們看看我能否讓事情變得更清晰。

Haskell在翻譯pure()時如何知道f是什麼? pure是一個類型類方法,所以這只是來自於我們所在類型的實例聲明。最近這種情況發生了變化,因此您可能需要按照不同的路徑才能找到答案,但結果結果相同:pure for Maybe is defined as Just

以同樣的方式,emptyis in Maybe, and is defined as Nothing

您將通過在ghci提示符處鍵入:i pure:i empty來了解類型類別提供的功能;那麼你可以尋求實例聲明Maybe爲他們。

從最近的觀點來看,這是不幸的,因爲如果不知道所使用的具體版本,就不會有明確的永久性答案。希望這會很快解決。

+0

這解決了我的問題,但是我在代碼中發現了一個新問題,'(x,y,z)< - attempt(i-6)'如何工作? '(X,Y,Z)'是一個元組,但'嘗試x'是'就了'或'Nothing',這將是非常感激,如果你可以再回答。 – CYC

+1

@CYC這就是'做'阻止工作。 [這是他們的解釋](https://en.wikibooks.org/wiki/Haskell/do_notation)。 – duplode