这段代码显然有效
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")
这段代码显然有效
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")
因为这不是如何<-
定义的。它转化为
readFile "in.txt" >>= \content ->
writeFile "out.txt" (map toUpper content)
您可以=<<
改用:
writeFile "out.txt" . map toUpper =<< readFile "in.txt"
首先,<-
不是运营商。这是一个特殊的语法元素,需要左侧的模式。
其次,如果它是一个中缀运算符,则$ <-
不会起作用,因为您不能有两个中缀运算符并排。
<-
从一元容器中“提取”一个值 。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 简化了这一点,并使编译器为您处理它。
你可以写如下
readFile "in.txt" >>= writeFile "out.txt" . map toUpper