Haskell 中的主函数是否总是以 main = do 开头?
Does the main-function in Haskell always start with main = do?
在java中我们总是这样写:
public static void main(String[] args){...}
当我们想开始编写程序时。
我的问题是,Haskell是否相同,即:我可以始终确保声明:
main = do,当我想为 Haskell?
中的程序编写代码时
例如:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name)
此程序将询问用户"What's your name?"
然后用户输入将存储在名称变量中,并且
"Hello" ++ name 会在程序终止前显示。
简答:否,我们必须声明一个main =
,但不一个do
.
main
必须是一个 IO monad 类型 (所以 IO a
),其中 a
是任意的(因为它被忽略了),如 here:
The use of the name main
is important: main
is defined to be the entry point of a Haskell program (similar to the main
function in C), and must have an IO
type, usually 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 " ++)
所以这里我们写了一个没有do
符号的main
。有关 脱糖 do
表示法的更多信息,请参阅 here。
是的,if 你的 do
块中有不止一行,而且 if 你甚至在使用do
表示法。
完整的 do
-notation 语法还包括显式分隔符 -- 大括号和分号:
main = do { putStrLn "What's your name?"
; name <- getLine
; putStrLn ("Hello " ++ name)
}
对于它们,缩进除了编码风格外没有任何作用(良好的缩进提高可读性;明确的分隔符确保代码的健壮性,消除与 white-space 相关的脆弱性)。所以当你只有一行 IO 代码时,比如
main = do { print "Hello!" }
没有分号,没有注意缩进,花括号和do
关键字本身变得多余:
main = print "Hello!"
所以,不,不总是。但它经常发生,并且代码的统一性对可读性有很大帮助。
do
块转换为单子代码,但您首先可以将此事实视为实现细节。事实上,你应该。您可以在心理上将 do
符号 公理化 视为一种嵌入式语言。而且,反正就是那个。
简化的 do
语法是:
do { pattern<sub>1</sub> <- action<sub>1</sub>
; pattern<sub>2</sub> <- action<sub>2</sub>
.....................
; return (.....)
}
每个 action<sub>i</sub>
都是 Haskell 类型 M a<sub> 的值i</sub>
对于一些 monad M
和一些结果类型 a<sub>i</sub>
。每个 action
产生自己的结果类型 a<sub>i</sub>
而 all action
s 必须属于 same monad 类型 M
.
每个 pattern<sub>i</sub>
从相应的操作中接收先前“计算”的结果。
通配符_
可以用来忽略它。如果是这种情况,_ <-
部分可以完全省略。
“Monad”是一个可怕的、没有信息量的词,但从概念上讲,它实际上只不过是 EDSL。 嵌入式 领域特定语言意味着我们有原生 Haskell 值代表(在这种情况下)I/O 计算。我们用这种语言编写我们的 I/O 程序,它成为原生 Haskell 值,我们可以像在任何其他原生 [=118] 上一样对其进行操作=] value -- 将它们收集在列表中,将它们组合成更复杂的计算描述(程序)等
main
值就是我们的 Haskell 程序计算出的一个这样的值。编译器看到它,并在 运行 时间执行它代表的 I/O 程序。
重点是我们现在可以拥有一个“函数”getCurrentTime
(从表面上看,在函数式范例中这是不可能的,因为它必须 return 在不同的调用中产生不同的结果) ,因为它 不是 return 当前时间 -- 它描述的动作 将 这样做,当 I/O 对其进行编程 描述 是 运行 按 运行 时间系统。
在类型级别上,这反映在这样的值中,这些值不仅具有一些普通的 Haskell 类型 a
,而且具有参数化类型 IO a
,由 [=30]“标记” =]属于这个特殊的I/O编程世界。
另请参阅:。
在java中我们总是这样写:
public static void main(String[] args){...}
当我们想开始编写程序时。
我的问题是,Haskell是否相同,即:我可以始终确保声明: main = do,当我想为 Haskell?
中的程序编写代码时例如:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name)
此程序将询问用户"What's your name?" 然后用户输入将存储在名称变量中,并且 "Hello" ++ name 会在程序终止前显示。
简答:否,我们必须声明一个main =
,但不一个do
.
main
必须是一个 IO monad 类型 (所以 IO a
),其中 a
是任意的(因为它被忽略了),如 here:
The use of the name
main
is important:main
is defined to be the entry point of a Haskell program (similar to themain
function in C), and must have anIO
type, usuallyIO ()
.
但你不一定需要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 " ++)
所以这里我们写了一个没有do
符号的main
。有关 脱糖 do
表示法的更多信息,请参阅 here。
是的,if 你的 do
块中有不止一行,而且 if 你甚至在使用do
表示法。
完整的 do
-notation 语法还包括显式分隔符 -- 大括号和分号:
main = do { putStrLn "What's your name?"
; name <- getLine
; putStrLn ("Hello " ++ name)
}
对于它们,缩进除了编码风格外没有任何作用(良好的缩进提高可读性;明确的分隔符确保代码的健壮性,消除与 white-space 相关的脆弱性)。所以当你只有一行 IO 代码时,比如
main = do { print "Hello!" }
没有分号,没有注意缩进,花括号和do
关键字本身变得多余:
main = print "Hello!"
所以,不,不总是。但它经常发生,并且代码的统一性对可读性有很大帮助。
do
块转换为单子代码,但您首先可以将此事实视为实现细节。事实上,你应该。您可以在心理上将 do
符号 公理化 视为一种嵌入式语言。而且,反正就是那个。
简化的 do
语法是:
do { pattern<sub>1</sub> <- action<sub>1</sub>
; pattern<sub>2</sub> <- action<sub>2</sub>
.....................
; return (.....)
}
每个 action<sub>i</sub>
都是 Haskell 类型 M a<sub> 的值i</sub>
对于一些 monad M
和一些结果类型 a<sub>i</sub>
。每个 action
产生自己的结果类型 a<sub>i</sub>
而 all action
s 必须属于 same monad 类型 M
.
每个 pattern<sub>i</sub>
从相应的操作中接收先前“计算”的结果。
通配符_
可以用来忽略它。如果是这种情况,_ <-
部分可以完全省略。
“Monad”是一个可怕的、没有信息量的词,但从概念上讲,它实际上只不过是 EDSL。 嵌入式 领域特定语言意味着我们有原生 Haskell 值代表(在这种情况下)I/O 计算。我们用这种语言编写我们的 I/O 程序,它成为原生 Haskell 值,我们可以像在任何其他原生 [=118] 上一样对其进行操作=] value -- 将它们收集在列表中,将它们组合成更复杂的计算描述(程序)等
main
值就是我们的 Haskell 程序计算出的一个这样的值。编译器看到它,并在 运行 时间执行它代表的 I/O 程序。
重点是我们现在可以拥有一个“函数”getCurrentTime
(从表面上看,在函数式范例中这是不可能的,因为它必须 return 在不同的调用中产生不同的结果) ,因为它 不是 return 当前时间 -- 它描述的动作 将 这样做,当 I/O 对其进行编程 描述 是 运行 按 运行 时间系统。
在类型级别上,这反映在这样的值中,这些值不仅具有一些普通的 Haskell 类型 a
,而且具有参数化类型 IO a
,由 [=30]“标记” =]属于这个特殊的I/O编程世界。
另请参阅: