如何理解 Monad 中的 <- in Haskell's do notation with an uncommon ">>=" 实现?

问题描述 投票:0回答:1

我是一名 C++/Rust 程序员,出于好奇,我目前正在学习 Haskell。正如所料,我在尝试理解 Monad 时遇到了一些障碍:

我已经在 Wikibook 上阅读了 Monad 的定义,包括它们与范畴论中的数学定义和三个 Monad 定律的关系。我也知道

do
符号是 Monad 的语法糖,但
do
块中的某些行为仍然让我困惑。

在一些教程中,我注意到

bind
(
>>=
) 通常被解释为 将第二个参数(函数)应用于第一个参数中包含的值并返回应用函数的结果。然而,从 Monad 法则的角度来看,这似乎并不是唯一可能的实现方式。我不确定
bind
是否必须始终遵循此模式,或者它是否只是一个 common 实现。

如果这种模式确实很常见,那么我必须考虑其他实现。最让我困惑的是我们知道:

do { v <- y; ... } = y >>= (\v -> ...)

所以这里

<-
的含义应该和
>>=
的实现有直接关系。但如果不是上面提到的常见实现,那么
<-
可能不再带有声明或绑定的语义。在这种情况下我们该如何理解呢?

不幸的是,作为一个初学者,尽管我付出了努力,但我还没有想到一个不常见但合法实施

bind
的例子。


以下是我的问题摘要:

  1. 是否存在仍然满足 Monad 定律的不常见的
    bind
    (
    >>=
    ) 实现?
  2. 在我认为
    bind
    的不常见实现下,如何理解
    <-
    符号中
    do
    的含义?
haskell monads
1个回答
0
投票

也许最简单的是list monad,其实现为:

instance Monad [] where
  return x = [x]
  x >>= f = [y | xi <- x, y <- f xi]

这里

x >>= f
本质上与
concatMap f x
相同,因此对于列表
xi
中的每个元素
x
调用该元素上的
f
,并将
f xi
生成的项目列表添加到结果中.

这意味着如果我们写:

foo :: [Int]
foo = do
    xi <- [1, 4, 2, 5]
    [xi, xi + 1]

翻译为:

[1, 4, 2, 5] >>= \xi -> [xi, xi + 1]

因此,对于列表中的每个项目

[1,4,2,5]
,产量
x
x+1
,所以:

ghci> foo
[1,2,4,5,2,3,5,6]

这里

那么

<-
可能不再带有 C 风格赋值或绑定的语义。

它并不真正具有 C 风格赋值的语义,即使使用

IO
也不行。在 Haskell 中,您不会为变量“赋值”。您声明一个变量,并且该变量始终保持相同的值。因此,您不能创建循环,例如“操纵”变量的值。不变性是声明性语言的核心特征之一。
© www.soinside.com 2019 - 2024. All rights reserved.