在java中我们总是写:
public static void main(String[] args){...}
当我们想开始编写程序时。
我的问题是,对于Haskell,IE是否相同:我总能确定声明: main = do,当我想在Haskell中为程序编写代码时?
例如:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name)
该程序将询问用户“你叫什么名字?” 然后,用户输入将存储在name-variable中,并且 程序终止前将显示“Hello”++名称。
答案 0 :(得分:10)
简短回答:否,我们必须声明main =
,但不 a do
。< / p>
main
必须是 IO monad 类型(所以IO a
)其中a
是任意的(因为它被忽略) ),正如here所写:
使用名称
main
很重要:main
被定义为Haskell程序的入口点(类似于C中的main
函数),并且必须拥有IO
类型,通常为IO ()
。
但您没有必要使用do
符号。实际上是do
is syntactical sugar。您的main
实际上是:
main =
putStrLn "What's your name?" >> getLine >>= \n -> putStrLn ("Hello " ++ n)
或更优雅:
main = putStrLn "What's your name?" >> getLine >>= putStrLn . ("Hello " ++)
所以我们写了main
没有do
符号。有关 desugaring do
表示法的更多信息,请参阅here。
答案 1 :(得分:1)
是的,如果你的 完整的 使用它们,缩进在编码风格中不起作用(良好的缩进提高了可读性;显式分隔符确保代码稳健性,消除与空白相关的脆性)。所以当你只有一行IO代码时,比如 没有分号,没有要注意的缩进,花括号和 所以,不,不是永远。但通常情况确实如此,代码的一致性对可读性有很大帮助。 简化的 对于某些monad 每个 通配符 &#34;单子&#34;这是一个可怕而且没有信息的词,但从概念上讲它实际上只不过是EDSL。 嵌入式特定于域的语言意味着我们拥有本机Haskell值(在本例中为 I / O计算)。我们用这种语言编写 I / O 程序,这些程序成为本机Haskell值,我们可以像任何其他本机Haskell值一样操作 - 将它们收集在列表中,将它们组合成更复杂的计算描述(程序)等。 关键是我们现在可以拥有一个&#34;功能&#34; do
块中有多行,而,如果你甚至使用do
符号。< / p>
do
- 符号语法还包括显式分隔符 - 花括号和分号:main = do { putStrLn "What's your name?"
; name <- getLine
; putStrLn ("Hello " ++ name)
}
main = do { print "Hello!" }
do
关键字本身就变得多余了:main = print "Hello!"
do
转换为IO
- monadic代码,但您可以将此事实视为实现细节。事实上,你应该。您可以在心理上将do
符号 axiomatically 视为嵌入式语言。此外,无论如何,就是这样。do
- 语法是: do { pattern1 <- action1
; pattern2 <- action2
.....................
; return (.....)
}
actioni
和某些结果类型M ai
,每个M
都是ai
类型的Haskell值,而每个操作都会生成自己的结果类型ai
} 所有操作必须属于相同的 monad类型M
。patterni
接收先前的&#34;计算的&#34;相应行动的结果。_
可用于忽略它。如果是这种情况,_ <-
部分可以完全省略。main
值是由我们的Haskell程序计算的一个这样的值。编译器会看到它,并在运行时执行它所代表的 I / O 程序。 getCurrentTime
(从表面而言,在功能范例中是不可能的,因为它必须在单独的调用上返回不同的结果),因为它不返回当前时间 - 它描述的动作< em>将
在类型级别上,这个值反映的是这些值不仅仅是一些普通的Haskell类型a
,而是一个参数化类型IO a
,&#34;标记为&#34; IO
属于 I / O 编程的这个特殊世界。