gaa*_*kam 4 io haskell program-entry-point
我正在阅读http://learnyouahaskell.com/ ...令我惊讶的是:
因此,
main
始终具有类型签名main :: IO something
,其中something
是一些具体类型。
?因此main
,不必一定是type IO()
,而可以是IO(String)
or 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:~$
Run Code Online (Sandbox Code Playgroud)
嗯 因此,我的第一个假设被反驳。我认为这是Haskell程序将退出状态返回到Shell的一种方式,就像C程序从其启动int main()
并使用return 0
或报告退出状态一样return 1
。
但是1
没有,上面的程序消耗了from输入的内容,然后什么也不做,特别是似乎没有将其返回1
给shell。
再测试一次:
m@m-X555LJ:~$ cat wtf.hs
main = getContents
m@m-X555LJ:~$ runhaskell wtf.hs
m@m-X555LJ:~$
Run Code Online (Sandbox Code Playgroud)
哇。这次,我尝试返回IO String
。由于我不知道的原因,这次Haskell 甚至没有像我回来时那样等待输入IO Int
。该程序似乎什么也不做。
这表明该值实际上没有返回任何地方:显然,由于没有在任何getContents
地方使用的结果,由于懒惰,整个指令被跳过了。但是,如果是这种情况,为什么IO Int
不跳过返回?是的:我做fmap read
了这个IO
动作;但是同样的东西似乎也适用,read
仅在使用操作结果的情况下才需要计算,而该结果(如main = getContents
示例所示)没有使用,因此懒惰也应该跳过read
,因此也跳过getLine
,对吗?好吧,错了-但是我很困惑为什么。
有什么用返回的IO Something
距离main
,而不是唯一的IO ()
?
这实际上是多个问题,但顺序如下:
main
没有意义,这就是为什么它可以是()
或其他任何含义的原因。根本不使用。IO ()
main 之外的其他原因类型是为了方便起见;否则,您总是必须要做一些main = void $ realMain
丢弃结果的操作(您可能希望执行一个操作,该操作可能会返回您不关心的结果,作为最后发生的事情),这有点乏味。恕我直言,默默地丢弃东西是不好的,所以我宁愿如果main
被迫这样做:: IO ()
,但您始终可以通过自己提供类型签名来获得这种效果,因此实际上这不是问题。System.Exit
fmap read getLine
会消耗输出而getContents
不会消耗输出,是因为它getContents
是懒惰的,getLine
而不是-即getLine
会在您认为合适的地方读取一行文本,而getContents
只有在Haskell世界中“需要”结果的情况下,才执行任何实际的IO。由于的结果IO
不会用于任何事情,这意味着如果getContents
整个结果都不会做任何事情main
。