0

我目前正在学习使用 monad 进行计算的基础知识。我一直在检查代码片段,我相信我知道它们的作用,但我可能需要澄清一下。它涉及 Maybe monad 的实例。

有一些函数试图计算尾部,还有一个函数试图计算列表的头部。下面的函数在使用列表调用时会产生等效的结果[1,2,3,4,5] = Just 3

该函数func3似乎“跳过”了一个额外的计算步骤func2。我是否正确地说,func3将计算结果输入到下面的尾部计算中,然后计算它的尾部,然后将该计算的结果传递给下面计算头部的函数?

如果是这样,那么为什么我们需要func2忽略初始计算的结果?在我看来,它好像在运行myTail xs计算,然后将其值传递给函数,该函数使用初始列表而不是尾部计算的结果。

因此,这只是说明每一个的多余步骤a, b, c吗?我假设这func3也相当于func1,只有最顶层的计算是a

非常感谢大家。

--computes head
myHead :: [a] -> Maybe a
myHead [] = Nothing
myHead (x:xs) = Just x

--computes tail
myTail :: [a] -> Maybe [a]
myTail [] = Nothing
myTail (x:xs) = Just xs


--below are all equivalent

func1 :: [a] -> Maybe a
func1 xs =
  do a <- myTail xs
     b <- myTail a
     c <- myHead b
     return c


func2 :: [a] -> Maybe a
func2 xs = 
   myTail xs >>=
     (\a -> myTail xs >>=
       (\b -> myTail b >>=
         (\c -> myHead c)))


func3 :: [a] -> Maybe a
func3 xs = 
   myTail xs >>=
     (\a -> myTail a >>=
       (\b -> myHead b))
4

2 回答 2

2

相当于规范 monad 操作中 func1 的do表示法,将变量移动到以下 lambda 的参数位置

func4 :: [a] -> Maybe a
func4 xs = 
   myTail xs >>= \a ->
       myTail a >>= \b ->
           myHead b >>= \c ->
               return c 

事实上最后一个 lambda 并没有改变前一行的结果,所以它可以被抑制导致 func3。

于 2014-05-11T11:33:40.503 回答
1

是的你是对的。func1、func2、func3 三个函数做同样的事情。func2 有一个额外的步骤,这是不必要的。func1 使用 do 表示法来表达与 func3 完全相同的计算。但是 func1 和 func2 的 a、b 和 c 是不一样的。

于 2014-05-11T11:30:50.353 回答