Haskell中的print是一个纯函数吗



Haskell中的print是纯函数吗;为什么?我认为它不是,因为它并不总是返回与纯函数应该返回的值相同的值。

类型为IO Int的值实际上不是Int。它更像是一张纸,上面写着"嘿,Haskell运行时,请以这样那样的方式生成Int值"。这张纸是惰性的,并且保持不变,即使运行时最终生成的Int是不同的。

通过将纸张分配给main,可以将其发送到运行时。如果IO操作从未妨碍main,而是在某个容器中搁置,那么它将永远不会被执行。

返回IO操作的函数与其他函数一样纯粹。他们总是归还同一张纸。运行时如何处理这些指令是另一回事。

如果它们不是纯的,我们在更改之前必须三思而后行

foo :: (Int -> IO Int) -> IO Int
foo f = liftA2 (+) (f 0) (f 0)

至:

foo :: (Int -> IO Int) -> IO Int
foo f = let x = f 0 in liftA2 (+) x x
是的,print是一个纯函数。它返回的值的类型为IO (),您可以将其视为输出传入字符串的一组代码。对于传入的每个字符串,它总是返回相同的代码。

如果您刚刚阅读纯函数的标记(一个函数,在给定相同的参数值的情况下,它总是计算为相同的结果值,并且不会导致任何语义上可观察到的副作用或输出,例如可变对象的突变或I/O设备的输出。)然后在打印类型中思考:

putStrLn :: String -> IO ()

你会在那里找到一个技巧,它总是返回IO (),所以…,它会产生效果。因此,就参考透明度而言,它并不纯粹例如,getLine返回IO String,但它也是一个纯函数。(@interjay贡献),我想说的是,答案非常接近这个问题:

就值而言,对于相同的输入,IO ()将始终是相同的IO ()

在执行问题上,它不是纯粹的,因为执行IO ()可能有副作用(在屏幕上放一个字符串这个案子看起来很无辜,但一些IO可能会吃到核弹然后返回Int 42)

你可以更好地理解@Ben在这里的好方法:

"有几种方法可以解释你是如何"纯粹"操纵的现实世界。一种是说IO就像一个状态monad,只是正在经历的状态是你之外的整个世界程序;=(所以你的Stuff->IO DBThing函数真的有一个额外的接收世界并实际返回DBThing与另一个世界;它总是用不同的名字来称呼世界,这就是为什么它甚至可以返回不同的DBThing值当用相同的Stuff调用时)。另一种解释是IODBThing的价值本身就是一个命令程序;你的Haskell程序一个完全纯的函数,不执行IO,返回一个不纯的程序执行IO,并且Haskell运行时系统(impuly)执行程序返回。">

和@Erik Allik:

因此,返回IO a类型值的Haskell函数实际上不是在运行时执行的函数——执行了什么IO本身就是一个值。所以这些函数实际上是纯的,但是它们的返回值表示非纯计算。

你可以在这里找到它们了解Haskell中的纯函数和IO

相关内容

  • 没有找到相关文章

最新更新