列表上的 monad 绑定操作不直观
monad bind operation on a list not intuitive to follow
我发现 Option
Monad 易于理解,而 List
则不然。
Some(1) >>= { x=>Some(x+1)}
Ma -> a -> Mb -> Mb
如果我从 Some(1) 中提取值,我知道它是 1
但在列表中
List(3,4,5) flatMap { x=> List(x,-x) }
如果我从列表中提取值,我会得到什么?如何让理解过程直观
Option
或 Maybe
背后的直觉实际上与 List
monad 非常相似。主要区别在于 List
是不确定的 - 我们不知道我们可以获得多少个值,当使用 Option
时它总是成功时为 1,失败时为 0。空列表被认为是失败的。
我觉得这个piece描述得很好:
For lists, monadic binding involves joining together a set of
calculations for each value in the list. When used with lists, the
signature of >>= becomes:
(>>=) :: [a] -> (a -> [b]) -> [b]
That is, given a list of a's and a function that maps an a onto a list
of b's, binding applies this function to each of the a's in the input
and returns all of the generated b's concatenated into a list.
还有一个 example 列表实现:
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
fail _ = []
很抱歉将 Haskell 放入 Scala 答案中,但那是我用来理解这些东西的资源。
Scala 的 flatMap
不完全是 Haskell 的绑定 >>=
,但非常接近它。那么这一切意味着什么?:
想象一个实际情况,您有一个客户列表 List[Client]
,您可以将它们绑定到单个订单列表 List[Order]
,该列表将自动为您展平 flatMap
或 >>=
。如果您改用 map
,则会得到 List[List[Order]]
。在实践中,您将为 >>=
提供函数以供使用,类似于您为 fold
提供函数的方式 - 您决定数据必须如何 generated/aggregated/etc。 bind 为您做的是提供一个通用模式来组合两个 monadic 值,并且对于每种类型的 monads 实现都是唯一的。
您可能更愿意将其视为多个抽象级别(从更一般到更少):
Monad 具有将两个 monadic 值合并为一个的绑定操作:(>>=) :: m a -> (a -> m b) -> m b
.
List
作为 monad 实例实现绑定,如下所示:xs >>= f = concat (map f xs)
- 将函数映射到所有元素并将结果连接到一个列表中。
您根据需要(客户 -> 订单示例)为绑定函数提供函数 f
的实现。
一旦您了解了 monad 实例的绑定行为(List
、Option
),您就可以考虑仅使用它和 "forget" 实际实现。
我发现 Option
Monad 易于理解,而 List
则不然。
Some(1) >>= { x=>Some(x+1)}
Ma -> a -> Mb -> Mb
如果我从 Some(1) 中提取值,我知道它是 1
但在列表中
List(3,4,5) flatMap { x=> List(x,-x) }
如果我从列表中提取值,我会得到什么?如何让理解过程直观
Option
或 Maybe
背后的直觉实际上与 List
monad 非常相似。主要区别在于 List
是不确定的 - 我们不知道我们可以获得多少个值,当使用 Option
时它总是成功时为 1,失败时为 0。空列表被认为是失败的。
我觉得这个piece描述得很好:
For lists, monadic binding involves joining together a set of calculations for each value in the list. When used with lists, the signature of >>= becomes:
(>>=) :: [a] -> (a -> [b]) -> [b]
That is, given a list of a's and a function that maps an a onto a list of b's, binding applies this function to each of the a's in the input and returns all of the generated b's concatenated into a list.
还有一个 example 列表实现:
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
fail _ = []
很抱歉将 Haskell 放入 Scala 答案中,但那是我用来理解这些东西的资源。
Scala 的 flatMap
不完全是 Haskell 的绑定 >>=
,但非常接近它。那么这一切意味着什么?:
想象一个实际情况,您有一个客户列表 List[Client]
,您可以将它们绑定到单个订单列表 List[Order]
,该列表将自动为您展平 flatMap
或 >>=
。如果您改用 map
,则会得到 List[List[Order]]
。在实践中,您将为 >>=
提供函数以供使用,类似于您为 fold
提供函数的方式 - 您决定数据必须如何 generated/aggregated/etc。 bind 为您做的是提供一个通用模式来组合两个 monadic 值,并且对于每种类型的 monads 实现都是唯一的。
您可能更愿意将其视为多个抽象级别(从更一般到更少):
Monad 具有将两个 monadic 值合并为一个的绑定操作:
(>>=) :: m a -> (a -> m b) -> m b
.List
作为 monad 实例实现绑定,如下所示:xs >>= f = concat (map f xs)
- 将函数映射到所有元素并将结果连接到一个列表中。您根据需要(客户 -> 订单示例)为绑定函数提供函数
f
的实现。
一旦您了解了 monad 实例的绑定行为(List
、Option
),您就可以考虑仅使用它和 "forget" 实际实现。