我正在尝试使用 Haskell 开发聊天服务器。
有很多有用的工具,比如TChan
, TSkiplist
, forkIO
...等等,但事实证明,我的大部分代码都是写在 IO monads 和 unsafePerformIO 中,这听起来效率很低。
这样做可以吗,或者 haskell 不是用于此目的的正确工具?
作为一般规则,首先尝试将代码编写为纯函数,而不用担心数据来自哪里——只要假设它就在那里。
接下来将纯函数包装在 IO 中,以提供纯函数数据并将结果放在某处。聊天应用程序中有很多这样的事情没关系!IO monad 一点也不低效,只是我们更喜欢尽可能多地保留代码,因为这是一个很好的设计——让数据处理与 IO 分开。聊天应用程序不会对其获取的数据进行大量计算,因此可以有大量的 IO 代码。
我认为坚持使用 IO monad 肯定比使用 unsafePerformIO 更好,因为 unsafePerformIO 将其结果呈现为纯数据。我可能很想用它从配置文件中获取常量,但我从来没有真正这样做过,而且如果你在 IO monad 中很忙,那也没有意义。它被称为不安全是有原因的!Petr Pudlák 在下面的评论中有很好的建议。
我听说 Haskell 的 monads 被描述为世界上最好的命令式编程语言。我可以在那个描述上分裂头发,但我同意这种观点,是的,坚持使用 Haskell。Haskell 擅长于您使用它的编程。
每当你注意到你有一个长函数驻留在 IO monad 中时,停下来看看发生的计算是值得的。根据我的经验,(几乎)总是发生一些与 IO 无关的事情,这些事情不需要访问输入输出并且可以封装在纯函数中。
这有一个很大的优势,它迫使您找到适当的抽象并将(纯)算法与输入/输出处理分开。此外,验证和测试纯函数要容易得多。当然,您仍然可以从某个IO a
函数(例如main
)中调用这些纯函数,但这完全没问题。
我的大部分代码都写在 IO monads 中
没关系。
和 unsafePerformIO
那很糟!避免unsafePerformIO
像瘟疫一样使用;它应该只在非常特殊的情况下由经验丰富的 Haskellers 使用。
这样做可以吗,或者 haskell 不是用于此目的的正确工具?
在 IO monad 中写代码是可以的,但使用unsafePerformIO
. 相反,学习如何使用Monad
接口(do
符号)组合 IO 操作。了解哪些函数类型签名需要包含该IO
类型。