在Java中,我们总是写下:
public static void main(String[] args){...}
当我们想开始编写程序时。
我的问题是,对于Haskell而言,这是相同的,即:我可以始终确保声明:main =做,当我想在haskell中编写代码时?
例如:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name)
此程序将询问用户"您的名字是什么?"然后,用户输入将存储在名称变量的内部,然后" Hello" 名称将在程序终止之前显示。
简短答案: no ,我们必须声明 main =
,但是 not> not> not> a do
。/p>main
必须是 io monad type (因此IO a
(a
是任意的(因为它被忽略了(,如这里:
名称
main
的使用很重要:main
被定义为Haskell程序的入口点(类似于C中的main
函数(,并且必须具有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 " ++)
因此,在这里我们编写了一个没有do
表示法的main
。有关 desugaring do
表示法的更多信息,请参见此处。
是,如果,您的do
块中有多个行,并且如果,您甚至使用do
note法。<<<<<<<<<<<<<<<<<<
完整的 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
-syntax是:
do { pattern1 <- action1
; pattern2 <- action2
.....................
; return (.....)
}
每个actioni
是某些MONAD M
和某些结果类型ai
的M ai
类型的Haskell值。每个action
都会产生自己的结果类型ai
,而所有 all action
S必须属于相同 Monad类型M
。
每个patterni
都会收到"计算"相应的动作结果。
通配符_
可用于忽略它。如果是这种情况,则可以完全省略_ <-
零件。
" monad"是一个可怕且非信息性的词,但实际上,它不过是概念上的EDSL。嵌入式特定于域的语言是指我们具有代表的本机Haskell值(在这种情况下( I/O Computations 。我们用这种语言编写我们的 i/o 程序,它成为本地haskell值,我们可以像其他任何其他本地Haskell值一样操作,将它们收集到列表中,将其归为更复杂的计算描述(程序(等
main
值是我们的Haskell程序计算的这样的值。编译器会看到它,并执行它代表的 i/o 程序,在运行时。
这一点是我们现在可以拥有"功能"。 getCurrentTime
(从表面上,在功能范式中不可能,因为它必须在单独的调用中返回不同的结果(,因为它不是不是返回当前时间 - 它描述的的动作 will 这样做,当 i/o 程序描述由运行时系统运行。
在类型级别上,这是由不仅具有某些普通haskell类型a
的值而反映的,而是参数化的类型, IO a
tagged;由 IO
属于 i/o 编程的这个特殊世界。
另请参见:为什么Haskell的绑定函数从非债券到monadic都具有一个函数。