2015-09-11 82 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