Haskell 哈斯凯尔的守卫与纯洁
我在读,有这样一个代码:Haskell 哈斯凯尔的守卫与纯洁,haskell,Haskell,我在读,有这样一个代码: 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)
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
因此,如果x>0,则:
attempt x
= (guard True) >> (r!x) = (pure ()) >> (r!x)
= (pure ()) >>= \_ -> r!x = (f ()) >>= (\_ -> r!x)
因此f()
应该是ma
类型(在这种情况下可能是a
),但是Haskell怎么知道f
是什么f()
可能返回empty
,因为它从未被指定过。(f
在纯文本中表示f
)
如果x>= 这是一个多问题的问题,但让我们看看我能否把事情说得更清楚一点 当解释
pure()
时,Haskell如何知道f
是什么pure
是一个类型类方法,因此它只是来自我们所处类型的实例声明。这一点最近发生了变化,因此您可能必须遵循不同的路径才能找到答案,但结果是相同的:
以同样的方式
通过在ghci提示符下键入:i pure
或:i empty
,您将了解typeclass提供了哪些函数;然后,您可以查找可能
为它们创建的实例声明
不幸的是,从这样一个角度来看,这种情况最近发生了变化,因此在不知道您使用的具体版本的情况下,没有明确的永久性答案。希望这会很快解决。在手动计算
尝试x的最后一个表达式中,您正在混淆类型和值<代码>纯::a->f a
不是定义;它是一个类型签名(请注意:
)。完整地说,pure
的类型是:
GHCi> :t pure
pure :: Applicative f => a -> f a
这里,f
代表Applicative
的任何实例,a
代表任何类型。在您的例子中,您使用的是Maybe
monad/applicative functor,因此f
是Maybe
。pure()
的类型是Maybe()
。(()::()
是当您对结果不感兴趣时使用的伪值。pure()
中的()
是一个值,但是中的()
可能()
是一个类型-()
值的类型)
我们将从您评估的最后一个正确步骤继续:
(pure ()) >>= \_ -> r!x
哈斯克尔怎么知道什么是[pure()
]
从某种意义上说,它不需要。这里使用pure()
的函数是(>>=)
。它有以下类型:
GHCi> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
将m
设置为可能
,与您的情况一样,我们得到:
Maybe a -> (a -> Maybe b) -> Maybe b
第一个参数的类型是可能是一个
,因此(>=)
能够处理任何可能是一个
值,包括纯()
,而不管它是一个只是
-某物还是无
。当然,它将以不同的方式处理只是
和什么都不
,因为这就是以下的要点:
我们还需要完成评估。要做到这一点,我们需要知道如何为Maybe
定义pure
。我们可以在以下内容中找到定义:
现在我们终于可以继续:
(pure ()) >>= \_ -> r!x
Just () >>= \_ -> r!x
(\_ -> r!x) () -- See the implementation of `(>>=)` above.
r!x
pure()::Maybe()==Just()
?@MephyMaybe()==Just()
如何应用于>=
?没有应用程序,pure()::Maybe()
被定义为Just()
,在的第634行。这解决了我的问题,但我在代码中发现了一个新问题,(x,y,z)@CYC这就是块的工作方式。
(Just x) >>= k = k x
Nothing >>= _ = Nothing
pure = Just
(pure ()) >>= \_ -> r!x
Just () >>= \_ -> r!x
(\_ -> r!x) () -- See the implementation of `(>>=)` above.
r!x