8

这段代码显然有效

import Data.Char

main = do
  content <- readFile "in.txt"
  writeFile "out.txt" (map toUpper content)

为什么这个没有?

import Data.Char

main = do
  writeFile "out.txt" (map toUpper $ <- readFile "in.txt")
4

4 回答 4

16

因为这不是如何<-定义的。它转化为

readFile "in.txt" >>= \content ->
writeFile "out.txt" (map toUpper content)

您可以=<<改用:

writeFile "out.txt" . map toUpper =<< readFile "in.txt"
于 2013-09-27T13:20:12.303 回答
16

首先,<-不是运营商。这是一个特殊的语法元素,需要左侧的模式。

其次,如果它是一个中缀运算符,则$ <-不会起作用,因为您不能有两个中缀运算符并排。

于 2013-09-27T13:20:19.917 回答
6

<-从一元容器中“提取”一个值 。IO是一个单子,所以它可以用来从一个IO动作中提取一个值。然而,Haskell 的语法说在使用它之前你必须把它绑定到一个名字上。实际上, the<-根本不是运算符,而是运算符的语法糖>>=(发音为“bind”)。所以当你写

main = do
    contents <- readFile "in.txt"
    writeFile "out.txt" (map toUpper contents)

它变成了

main = readFile "in.txt" >>= (\contents -> writeFile "out.txt" (map toUpper contents))

现在,想象一下如果你在main. 也许您使用 提取了多个值<-,并且某些表达式一次使用了多个这些值。您绝对可以编写“脱糖”版本,但它会开始变得非常非常困难。do-notation 简化了这一点,并使编译器为您处理它。

于 2013-09-27T13:23:51.477 回答
3

你可以写如下

readFile "in.txt" >>= writeFile "out.txt" . map toUpper
于 2013-09-27T13:19:09.083 回答