如果我知道(或合理地预期)IO操作是引用透明的,我可以在其上使用unsafePerformIO吗?还是有其他条件?

时间:2013-06-28 14:48:41

标签: haskell io

假设我有一个函数foo :: String -> IO String,它向Web服务发出请求,下载一些数据,解析它并返回一个字符串。我知道,在给定相同的请求字符串的情况下,Web服务将始终返回相同的字符串,除非缺少某种类型的互联网连接。这是否足以“安全”使用unsafePerformIO,并知道它永远不会导致问题?或者我必须确定其他一些事情吗?

编辑:我考虑这个的原因是因为我有一个函数deduce :: (String -> String) -> String,它将输入函数作为参数,并通过用不同的参数进行评估来推导出函数的某些属性。现在我想推断出这个Web服务的一些属性,但没有unsafePerformIO我将不得不大幅改变deduce,包括将其类型签名更改为deduce :: (String -> IO String) -> String,这意味着我需要更改所有其他函数我可能想要推断出属性。

1 个答案:

答案 0 :(得分:11)

不要那样做。 unsafePerformIO用于绑定外来原语,执行深层数据结构黑客攻击,有时建立顶级可变状态。

这听起来很安全,但这是一个糟糕的主意,因为当你不期望它们时,你现在会神奇地发生连接,从而使你的程序的其余部分在资源使用方面更难以推理等。 / p>

正如大家所知,如果服务确实总是返回相同的字符串,那么使用Template Haskell在编译时一劳永逸地发出请求会更安全,更有效。

编辑:好的,我现在看到了这个问题。但是你不必改变你想要推断的其他函数的类型。

如果f的类型为String -> String,则您始终可以获得return . f :: String -> IO String。所以不要搞砸你的其他功能,只需用返回来组合它们。现在,您可以轻松地处理有效和纯粹的代码..