list - 在新行中打印列表元素

标签 list haskell monads monad-transformers

我只是对列表和单子(monad)完全感到困惑,所以也许我的问题不正确或非常幼稚。
我已经看到了使用 mapM_ func here 的方法:

mapM_ print [1, 2, 3, 4]

但我不确切知道它是如何工作的,并且想知道如何以这样的方式做到这一点:
x <- [1, 2, 3]
print x

或者,如果我理解正确:
[1, 2, 3] >>= print

我知道 [1, 2, 3] 的类型为 [a]打印类型为 Show a => a -> IO () .我也知道使用 monad List 我们需要输入 List a在左侧和 func 类型为 a -> List b在右侧。我对吗?
你能帮我解决这个问题吗?

更新 .感谢@MathematicalOrchid 解释 mapM_ 的工作原理。从我的角度来看,我想解释真正的问题不是在不同的行中打印任何结果,而是以 monad List 提供的方式执行一些 monadic 操作(因为现在我正在闲逛 OpenGL 的东西)。但我知道误解的根源在于混合单子(monad)。

UPD2 .谢谢大家的回答。我为这个模糊的问题道歉。我不完全知道我需要什么答案以及问题是什么。那是因为我不了解一些基础知识。所以现在很难选择“正确的答案”,因为每个答案都与我正在寻找的东西有点和平。我决定选择最接近我想要的(虽然现在不是最有用的)。

最佳答案

您似乎在这里混淆了几件事。 (特别是,列表形成了一个 monad,而 I/O 形成了一个不同的 monad。)我将尝试澄清这一点......

首先,print函数接受任何可显示的内容并将其写入标准输出,然后是换行符。所以print [1, 2, 3]工作得很好,但显然将所有内容都写在同一行。要在单独的行上写东西,我们需要单独调用 print对于每个项目。到现在为止还挺好。
map function 将函数应用于列表的每个元素。所以map print [1, 2, 3]将申请 print到列表中的每个项目。但是,结果是 I/O 操作列表。这不是我们所追求的。我们想要执行这些操作,而不是列出它们。

方法是使用 >>运算符,它将两个 I/O 操作链接在一起(前提是您对它们的结果不感兴趣 - 并且打印某些内容不会返回任何有趣的内容)。所以foldr (>>) (return ())将获取您的 I/O 操作列表并将其转换为单个 I/O 操作。这个函数实际上已经定义好了;它被称为 sequence .

但是,map + sequence是一个如此常见的组合,它也已经被定义;它被称为 mapM_ . (还有 mapM ,没有下划线,如果你想保留结果。但是打印不会返回任何东西,所以没有必要。)

这就是为什么mapM_作品。现在你问为什么其他几种方法都行不通......

x <- [1, 2, 3]
print x

这根本行不通。第一行在列表 monad 中。但第二行在 I/O monad 中。你不能那样做。 (你会得到一个相当莫名其妙的类型检查错误。)我应该指出这是 Haskell 所谓的“do-notation”,上面的片段需要 do前面的关键字使其实际上是有效的语法:
do
  x <- [1, 2, 3]
  print x

无论哪种方式,它仍然无法正常工作。它几乎做了map print [1, 2, 3]有,但不完全。 (正如我所说,它不会进行类型检查。)

您还建议[1, 2, 3] >>= print ,这与前面的代码片段相同。 (实际上,编译器将前者转换为后者。)出于同样的原因,原版不进行类型检查,而本版也不进行类型检查。

这有点像尝试将数字添加到矩阵中。数字是可加的东西。矩阵是可添加的东西。但是您不能将一个添加到另一个,因为它们不一样。如果这是有道理的。

关于list - 在新行中打印列表元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12461871/

相关文章:

haskell - 你如何在 Haskell 中创建一个通用的 memoize 函数?

haskell - 如何调用部分未嵌套的变压器?

list - 如何将列表中的连续数字组合到 Haskell 中的范围中?

java - 在忽略字段的列表中查找重复项

c++ - 链表 - 覆盖数据

haskell - 在类型类中使用代理

haskell - 部分应用程序在运行时如何表示?

list - 如何在没有 GADT 或数据类型上下文的情况下定义 List 的 Eq 实例

haskell - 为什么 DefaultSignatures 不允许具体类型?

haskell - 使用 - 在 haskell 中加入两个 IO