6

在java中,我们总是写:

public static void main(String[] args){...}

当我们想开始编写程序时。

我的问题是,对于 Haskell,IE 是否一样:当我想在 Haskell 中为程序编写代码时,我是否可以始终确保声明:main = do?

例如:

main = do  
    putStrLn "What's your name?"  
    name <- getLine 
    putStrLn ("Hello " ++ name) 

该程序将询问用户“你叫什么名字?” 然后用户输入将存储在名称变量中,并且“Hello”++名称将在程序终止之前显示。

4

2 回答 2

12

简短的回答,我们必须声明 a main =,但不是a do

main必须是IO monad类型(so IO a),其中是任意的a(因为它被忽略),如下所示

名称的使用main很重要:main被定义为 Haskell 程序的入口点(类似于mainC 中的函数),并且必须有一个IO类型,通常是IO ().

但你不必需要do符号。其实do语法糖。你main的实际上是:

main =
    putStrLn "What's your name?" >> getLine >>= \n -> putStrLn ("Hello " ++ n)

或者更优雅:

main = putStrLn "What's your name?" >> getLine >>= putStrLn . ("Hello " ++)

所以这里我们写了一个main不带do符号的。有关脱糖 do符号的更多信息,请参见此处

于 2017-06-23T18:35:43.687 回答
4

是的,如果do您的块中有不止一行,并且甚至使用该do符号。

完整的do-notation 语法还包括显式分隔符——花括号和分号:

main = do { putStrLn "What's your name?" 
          ; name <- getLine  
          ; putStrLn ("Hello " ++ name) 
          }

有了它们,缩进除了编码风格之外没有任何作用(良好的缩进提高了可读性;显式分隔符确保了代码的健壮性,消除了与空白相关的脆弱性)。所以当你只有一行 IO 代码时,比如

main = do { print "Hello!" }

没有分号,没有需要注意的缩进,花括号和do关键字本身变得多余:

main = print "Hello!" 

所以,不,并非总是如此。但很多时候确实如此,而且代码的统一性对可读性大有帮助。


do块转换为一元代码,但您可以首先将此事实视为实现细节。事实上,你应该。您可以在精神上将do符号公理化地视为嵌入式语言。此外,无论如何,就是这样。

简化的do- 语法是:

   do {  pattern1 <- action1
      ;  pattern2 <- action2
      .....................
      ;  return (.....)
      }

每个都是一些 monad和一些结果类型的 Haskell 类型值。每个都产生自己的结果类型,而所有s 必须属于相同的monad 类型。actioniM aiMaiactionai actionM

每个都从相应的操作接收先前“计算”的结果。patterni

通配符_可以用来忽略它。如果是这种情况,则_ <-可以完全省略该部分。


“Monad”是一个可怕且无信息的词,但从概念上讲,它实际上只不过是 EDSL。嵌入式领域特定语言意味着我们有原生的 Haskell 值代表(在这种情况下)I/O 计算。我们用这种语言编写我们的I/O程序,它成为一个原生 Haskell 值,我们可以像对任何其他原生 Haskell 值一样对其进行操作——将它们收集在列表中,将它们组合成更复杂的计算描述(程序) , ETC。

main值是我们的 Haskell 程序计算的一个这样的值。编译器看到它,并在运行时执行它所代表的I/O程序。

关键是我们现在可以拥有一个“函数” getCurrentTime(从表面上看,在函数范式中是不可能的,因为它必须在单独的调用上返回不同的结果),因为它没有返回当前时间——它的动作当它描述的I/O程序由运行时系统运行时, describes这样做。

在类型级别上,这些值反映的不仅仅是一些普通的 Haskell 类型a,而是一个参数化类型,IO a被“标记”IO为属于这个特殊的I/O编程世界。

另请参阅:为什么 haskell 的 bind 函数将函数从 non-monadic 转换为 monadic

于 2017-06-23T18:48:02.510 回答