在haskell中等于(=)Vs左箭头(&lt ;-)符号

时间:2015-02-20 08:19:18

标签: haskell

工作代码:

import System
main = do
     [file1, file2] <- getArgs
     --copy file contents
     str <- readFile file1
     writeFile file2 str

崩溃代码:

import System
main = do
       [file1, file2] = getArgs
       str = readFile file1
       writeFile file2 str

当我尝试时,它抛出了一个错误:

  

a.hs:6:18:对输入'='

进行解析错误

那么<-=有何不同?

4 个答案:

答案 0 :(得分:81)

要了解真正的区别,你必须了解monad,以及@rightfold在回答中所描述的堕落。

对于IO monad的特定情况,如在getArgs示例中,粗略但有用的直觉可以如下:

  • x <- action 运行 IO action,获取其结果,并将其绑定到x
  • let x = actionx定义为等同于action,但不会运行任何内容。稍后,您可以使用y <- x表示y <- action

来自允许闭包的命令式语言的程序员可以使用Javascript绘制这种粗略的并行比较:

var action = function() { print(3); return 5; }

// roughly equivalent to x <- action
print('test 1')
var x = action()  // output:3
// x is 5

// roughly equivalent to let y = action
print('test 2')
var y = action    // output: nothing
// y is a function

// roughly equivalent to z <- y
print('test 3')
var z = y()       // output:3
// z is 5

再次说明:此比较仅关注IO。对于其他monad,您需要检查>>=实际上是什么,并考虑do的消亡。

答案 1 :(得分:44)

do
    x <- y
    f x

相当于:

y >>= \x -> f x

do
    let x = y
    f x

相当于

f y

即。 let / =没有monadic绑定而<-没有。

答案 2 :(得分:14)

代码无法编译,因为类型不匹配。让我们加载GHCI会话并查看您正在使用的功能类型 -

> :t writeFile
writeFile :: FilePath -> String -> IO ()
>
> :t readFile
readFile :: FilePath -> IO String

因此writeFile需要FilePathString。您希望从String获取readFile - 但readFile返回IO String而不是String

Haskell是一种非常有原则的语言。它区分函数(每次使用相同的参数调用时都提供相同的输出)和不纯的代码(可能会产生不同的结果,例如,如果功能取决于一些用户输入)。处理输入/输出(IO)的函数始终具有标记为IO的返回类型。类型系统确保您不能在纯函数中使用不纯的IO代码 - 例如,不是返回String函数readFile,而是返回IO String

这是<-符号很重要的地方。它允许您到达String内的IO,并确保无论您使用该字符串做什么,您定义的函数将始终标有IO。比较以下内容 -

> let x = readFile "tmp.txt"
> :t x
x :: IO String

这不是我们想要的,对此

> y <- readFile "tmp.txt"
> :t y
y :: String

这就是我们想要的。如果您有一个返回IO a并且想要访问a的函数,则需要使用<-将结果分配给名称。如果您的功能没有返回IO a,或者您不希望进入a内的IO,那么您可以使用=

答案 3 :(得分:12)

let x = readFile file1

这会采取行动&#34; readFile file1&#34;并在x中存储动作

x <- readFile file1

执行动作&#34; readFile file1&#34;并在x中存储操作的结果

在第一个示例中,x是未执行的I / O操作对象。在第二个示例中,x是磁盘上文件的内容。