假设我有一个函数 foo::String -> IO String
,它向 Web 服务发出请求、下载一些数据、解析它并返回一个字符串。我知道,给定相同的请求字符串,Web 服务将始终返回相同的字符串,除非缺少此类互联网连接。这些信息是否足以“安全”使用 unsafePerformIO
并知道它永远不会导致问题?或者我还必须确定其他一些事情吗?
编辑:我考虑这一点的原因是因为我有一个函数 deduce::(String -> String) -> String
它将采用输入函数作为参数并推断出通过使用不同的参数对其进行评估来评估该函数。现在我想推断出此 Web 服务的一些属性,但如果没有 unsafePerformIO
,我将不得不大幅更改 deduce
,包括将其类型签名更改为 deduce::(String -> IO String) -> String
这意味着我需要更改所有其他我可能想要推断其属性的函数。
最佳答案
不要那样做。 unsafePerformIO
用于绑定(bind)外部原语,进行深度数据结构黑客攻击,有时还建立顶级可变状态。
这听起来很安全,但这是一个坏主意,因为现在您会在意想不到的情况下神奇地发生连接,从而使程序的其余部分在资源使用等方面更难以推理。
正如人们所指出的,如果服务确实总是返回相同的字符串,那么使用 Template Haskell 在编译时一次性发出请求会更安全、更高效。
编辑:好的,我现在看到了这个问题。但您不必更改要推断的其他函数的类型。
如果 f
的类型是 String -> String
,那么你总是可以获得 return 。 f::字符串 -> IO 字符串
。所以不要搞乱你的其他函数,只需用 return 组合它们即可。现在您可以同样轻松地处理有效和纯代码..
关于haskell - 如果我知道(或合理预期)IO 操作是引用透明的,我可以对其使用 unsafePerformIO 吗?或者还有其他条件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17367530/