2013-09-27 18 views
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") 

回答

17

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

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

你可以使用=<<代替:

writeFile "out.txt" . map toUpper =<< readFile "in.txt" 
3

你可以如下

readFile "in.txt" >>= writeFile "out.txt" . map toUpper 
+0

或'map toUpper <$> readFile“in.txt”>> = writeFile“out.txt”'。不过,我认为OP要求解释而不是单纯的解决方案 – nponeccop

17

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

其次,如果它是一个中缀操作符,$ <-将不起作用,因为您不能有两个相邻的中缀操作符。

6

<-“提取”来自一元容器的值。 IO是一个monad,因此它可用于从IO操作中提取值。但是,Haskell的语法表示,在使用它之前,您必须将其绑定到名称。实际上,<-根本不是运营商,而是>>=运营商的语法糖(发音为“绑定”)。所以,当你写

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

它被变成

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

现在,想象一下,如果你在main有很多条语句。也许你用<-提取了几个值,并且某些表达式同时使用了多个这些值中的一个。你完全可以写出“desugared”版本,但它会变得非常非常困难。该符号简化了这一点,并使编译器为您处理它。