2

我有一个关于上下文价值的小问题。

  • Take Just 'a',所以Maybe在这种情况下类型上下文中的值是'a'

  • Take [3],所以[a]在这种情况下类型上下文中的值是3

  • 如果你[3]像这样应用 monad: [3] >>= \x -> [x+3],这意味着你x用 value 赋值3。没关系。

但是现在, take [3,2],那么 type 上下文中的值是什么[a]?很奇怪,如果你像这样申请 monad:

[3,4] >>= \x -> x+3  

它得到了正确的答案[6,7],但实际上我们不明白在这种情况下x是什么。您可以回答,啊x是 3,然后是 4,x向函数提供 2 次并按原样连接Monadconcat (map f xs)像这样:

[3,4] >>= concat (map f x) 

所以在这种情况下,[3,4]将分配给x。这意味着错误,因为[3,4]不是一个值。Monad是错的。

4

4 回答 4

6

我认为您的问题过于关注价值观。monad 是一个类型构造函数,因此不关心有多少和什么样的值,而关心上下文。

AMaybe a可以是a,也可以什么都不是。很简单,你正确地观察到了这一点。

AnEither String a要么是 some a,要么是 a 形式的一些信息String(例如,为什么计算a失败)。

最后,[a]是未知数量的as(或根本没有),这可能是由模棱两可的计算产生的,或者是一个给出多个结果的结果(如二次方程)。


现在,对于 的解释(>>=),了解 monad 的基本属性(范畴论者如何定义)是有帮助的

join :: m (m a) -> m a.

加上fmap(>>=)可以写成join

以下是什么join意思:一个上下文,再次放在相同的上下文中,仍然具有相同的结果行为(对于这个 monad)。

这一点很明显Maybe (Maybe a): 某些东西本质上可以是Just (Just x), or Nothing, or Just Nothing, 提供与 . 相同的信息Nothing。因此,Maybe (Maybe a)您可以不使用 ,Maybe a而不会丢失任何信息。就是这样join做的:它转换为“更容易”的上下文。

[[a]]不知何故更困难,但并不多。从多个/不明确的结果中,您基本上有多个/不明确的结果。一个很好的例子是四次多项式的根,它是通过求解一个二次方程找到的。你首先得到两个解,从每个解中你可以找到另外两个,得到四个根。

但关键是,无论您谈论的是模棱两可的模棱两可的结果,还是只是一个模棱两可的结果。您可以始终使用上下文“模糊”,并使用join.

这就是(>>=)列表的作用:它将模棱两可的函数应用于模棱两可的值:

squareRoots :: Complex -> [Complex] 

fourthRoots num = squareRoots num >>= squareRoots

可以改写为

fourthRoots num = join $ squareRoots `fmap` (squareRoots num)
-- [1,-1,i,-i]    <-  [[1,-1],[i,-i]]  <-       [1,-1] <- 1

因为您所要做的就是为每个可能的值找到所有可能的结果。

这就是为什么joinconcat列表,事实上

m >>= f == join (fmap f) m

必须在任何单子中成立。

可以给出类似的解释IO。具有副作用的计算,也可能具有副作用 ( IO (IO a)),本质上只是具有副作用的东西

于 2012-11-23T17:19:23.390 回答
3

你必须相当广泛地理解“上下文”这个词。

解释值列表的一种常见方式是它表示一个不确定的值,因此 [3,4] 表示一个值是 3 还是 4,但我们不知道是哪个(也许我们只知道它是 x^ 的解) 2 - 7x + 12 = 0)。

如果我们然后将 f 应用于它,我们知道它是 6 或 7,但我们仍然不知道哪个。

您更习惯的不确定值的另一个示例是 3。它可能意味着 3::Int 或 3::Integer,有时甚至是 3.0::Double。感觉更容易,因为只有一个符号代表不确定的值,而在列表中,所有可能性都列出了(!)。

如果你写

asum = do
   x <- [10,20]
   y <- [1,2]
   return (x+y)

您将获得一个包含四个可能答案的列表: [11,12,21,22]
这是您可以添加 x 和 y 的每种可能方式的一个。

于 2012-11-23T16:17:29.937 回答
1

不是上下文中的值,而是类型。

Just 'a' :: Maybe Char---CharMaybe上下文中。

[3, 2] :: [Int]---Int[]上下文中。

中是否有一个、没有或多个am a无关紧要的。

编辑:考虑(>>=) :: Monad m => m a -> (a -> m b) -> m b.

你举个例子Just 3 >>= (\x->Just(4+x))。但考虑Nothing >>= (\x->Just(4+x))。在上下文中没有任何价值。但是类型在上下文中都是一样的。

x认为必须是单个值是没有意义的。x有一个类型。如果我们正在处理Identitymonad,那么x将是一个值,是的。如果我们在Maybemonad 中,x它可能是一个单一的值,或者它可能根本就不是一个值。如果我们在列表 monad 中,x可能是单个值,或者根本不是值,或者是各种不同的值……但它不是所有这些不同值的列表。

你的另一个例子--- [2, 3] >>= (\x -> x + 3)---[2, 3]没有传递给函数[2, 3] + 3会有类型错误。2传递给函数。也是如此3。该函数被调用两次,为这两个输入提供结果,然后由>>=操作员组合结果。[2, 3]没有传递给函数。

于 2012-11-23T16:57:50.130 回答
0

“上下文”是我最喜欢的思考 monad 的方式之一。但是你有一个小小的误解。

取 Just 'a',因此在这种情况下 Maybe 类型的上下文中的值是 'a'

不完全的。您一直在说the value in context,但上下文“内部”并不总是有一个值,或者如果有,那么它不一定是唯一的值。这一切都取决于我们正在谈论的背景

Maybe上下文是“可空性”或潜在缺席的上下文。那里可能有东西,或者可能有Nothing。的“内部”没有价值Nothing。所以可能的上下文可能在内部有一个值,也可能没有。如果我给你一个Maybe Foo,那么你不能假设有一个Foo相反,您必须假设它是Foo 实际可能存在的上下文的内部Nothing。你可能会说某类型的东西Maybe Foo可空Foo的。

取 [3],因此在这种情况下,类型 [a] 的上下文中的值为 3

再说一次,不太对。一个列表代表一个不确定的上下文。我们不太确定价值”应该是什么,或者根本没有。如果是单例列表,例如[3],那么是的,只有一个。但是考虑列表的一种方法[3,4]是将其视为一些不可观察的值,我们不太确定它是什么,但我们确定它3或它是4。您可能会说某种类型的东西[Foo]不确定Foo的。


[3,4] >>= \x -> x+3

这是一个类型错误;不太清楚你的意思。

所以在这种情况下,[3,4]将分配给 x。这意味着错误,因为[3,4]不是一个值。单子错了。

你在这里完全失去了我。每个实例Monad都有自己的实现>>=,定义了它所代表的上下文。对于列表,定义是

(xs >>= f) = (concat (map f xs))

您可能想了解与 的概念相关的Functor和操作,并可能有助于消除一些困惑。ApplicativeMonad

于 2012-11-23T22:45:31.807 回答