main 返回 IO Something 而不是 IO() 有什么用?
What's the use of main returning IO Something rather than IO()?
我正在阅读 http://learnyouahaskell.com/ ... 让我感到惊讶的是:
Because of that, main
always has a type signature of main :: IO something
, where something
is some concrete type.
?所以 main
不一定是 IO()
类型,而是可以是 IO(String)
或 IO(Int)
?但这有什么用呢?
我玩了一些...
m@m-X555LJ:~$ cat wtf.hs
main :: IO Int
main = fmap (read :: String -> Int) getLine
m@m-X555LJ:~$ runhaskell wtf.hs
1
m@m-X555LJ:~$ echo $?
0
m@m-X555LJ:~$
嗯。所以我的第一个假设被推翻了。我认为这是 Haskell 程序从 return 退出状态到 shell 的一种方式,就像 C 程序从 int main()
开始并使用 [= 报告退出状态一样20=] 或 return 1
.
但是没有:上面的程序从输入中消耗了 1
然后什么都不做,特别是似乎没有 return 这个 1
到 shell.
再测试一次:
m@m-X555LJ:~$ cat wtf.hs
main = getContents
m@m-X555LJ:~$ runhaskell wtf.hs
m@m-X555LJ:~$
哇。这次我尝试 returning IO String
。由于我不知道的原因,这次 Haskell 甚至 甚至 都没有等待输入,就像我 returning IO Int
时那样。该程序似乎什么都不做。
这暗示该值实际上未在任何地方 return 编辑:显然,由于 getContents
的结果未在任何地方使用,因此由于懒惰而跳过了整个指令。但如果是这样的话,为什么 returning IO Int
没有被跳过?是的:我在 IO
动作上做了 fmap read
;但同样的东西似乎适用,只有在使用操作结果时才需要计算 read
,而正如 main = getContents
示例似乎暗示的那样 - 未使用,因此懒惰也应该跳过read
,因此也是 getLine
,对吧?好吧,错了 - 但我很困惑为什么。
从 main
而不是仅 IO ()
returning IO Something
有什么用?
这其实是多道题,但是顺序是:
main
的 'result' 没有意义,这就是为什么它 可以 是 ()
或其他任何东西。根本没用过。
- main 允许
IO ()
以外的类型是为了方便;否则你总是不得不做类似 main = void $ realMain
的事情来丢弃结果(你可能希望有一个可以 return 一个你不关心的结果的动作作为最后发生的事情)这有点乏味。恕我直言,默默地丢弃东西是不好的,所以我更喜欢 main
被强制为 :: IO ()
,但你总是可以通过自己提供类型签名来获得这种效果,所以这在实践中并不是真正的问题.
- 旁白:如果您想使用特定的退出代码退出,请使用
System.Exit
fmap read getLine
消耗输出而 getContents
不消耗输出的原因是因为 getContents
是懒惰的而 getLine
不是 - 即 getLine
读取一行文本,你认为它确实如此,而 getContents
仅在 Haskell 世界中结果为 "needed" 时才执行任何实际 IO;由于 IO
的结果没有用于任何事情,这意味着如果 getContents
是你的整个 main
. 它什么也不会做
我正在阅读 http://learnyouahaskell.com/ ... 让我感到惊讶的是:
Because of that,
main
always has a type signature ofmain :: IO something
, wheresomething
is some concrete type.
?所以 main
不一定是 IO()
类型,而是可以是 IO(String)
或 IO(Int)
?但这有什么用呢?
我玩了一些...
m@m-X555LJ:~$ cat wtf.hs
main :: IO Int
main = fmap (read :: String -> Int) getLine
m@m-X555LJ:~$ runhaskell wtf.hs
1
m@m-X555LJ:~$ echo $?
0
m@m-X555LJ:~$
嗯。所以我的第一个假设被推翻了。我认为这是 Haskell 程序从 return 退出状态到 shell 的一种方式,就像 C 程序从 int main()
开始并使用 [= 报告退出状态一样20=] 或 return 1
.
但是没有:上面的程序从输入中消耗了 1
然后什么都不做,特别是似乎没有 return 这个 1
到 shell.
再测试一次:
m@m-X555LJ:~$ cat wtf.hs
main = getContents
m@m-X555LJ:~$ runhaskell wtf.hs
m@m-X555LJ:~$
哇。这次我尝试 returning IO String
。由于我不知道的原因,这次 Haskell 甚至 甚至 都没有等待输入,就像我 returning IO Int
时那样。该程序似乎什么都不做。
这暗示该值实际上未在任何地方 return 编辑:显然,由于 getContents
的结果未在任何地方使用,因此由于懒惰而跳过了整个指令。但如果是这样的话,为什么 returning IO Int
没有被跳过?是的:我在 IO
动作上做了 fmap read
;但同样的东西似乎适用,只有在使用操作结果时才需要计算 read
,而正如 main = getContents
示例似乎暗示的那样 - 未使用,因此懒惰也应该跳过read
,因此也是 getLine
,对吧?好吧,错了 - 但我很困惑为什么。
从 main
而不是仅 IO ()
returning IO Something
有什么用?
这其实是多道题,但是顺序是:
main
的 'result' 没有意义,这就是为什么它 可以 是()
或其他任何东西。根本没用过。- main 允许
IO ()
以外的类型是为了方便;否则你总是不得不做类似main = void $ realMain
的事情来丢弃结果(你可能希望有一个可以 return 一个你不关心的结果的动作作为最后发生的事情)这有点乏味。恕我直言,默默地丢弃东西是不好的,所以我更喜欢main
被强制为:: IO ()
,但你总是可以通过自己提供类型签名来获得这种效果,所以这在实践中并不是真正的问题. - 旁白:如果您想使用特定的退出代码退出,请使用
System.Exit
fmap read getLine
消耗输出而getContents
不消耗输出的原因是因为getContents
是懒惰的而getLine
不是 - 即getLine
读取一行文本,你认为它确实如此,而getContents
仅在 Haskell 世界中结果为 "needed" 时才执行任何实际 IO;由于IO
的结果没有用于任何事情,这意味着如果getContents
是你的整个main
. 它什么也不会做