在哈斯克尔勺不安全?

所以Haskell有一个叫做汤匙的库,可以让我这样做

safeHead :: [a] -> Maybe a
safeHead = spoon . head

但它也让我这样做

>>> spoon True             :: Maybe Bool
Just True
>>> spoon (error "fork")   :: Maybe Bool
Nothing
>>> spoon undefined        :: Maybe Bool
Nothing
>>> spoon (let x = x in x) :: Maybe Bool
<... let's just keep waiting...>

这在某些情况下似乎非常有用,但是它也违反了指称语义(根据我的理解),因为它允许我在的语义原像中区分不同的事物。 这比throw / catch更强大,因为它们可能具有由continuations定义的语义。

>>> try $ return (error "thimble") :: IO (Either SomeException Bool)
Right *** Exception: thimble

所以我的问题是:有人可以使用勺子恶意破坏类型安全吗? 便利是否值得冒险? 或者更现实的说,是否有一种合理的方式使用它会削弱某人对程序意义的信心?


有一个棘手的地方,如果你使用它,做一个看起来像无辜的重构可以改变程序的行为。 没有任何花里胡哨的,就是这样:

f h x = h x
isJust (spoon (f undefined)) --> True

但是也许这本书中最常见的haskell转换,eta收缩,就是f

f h = h
isJust (spoon (f undefined)) --> False

由于seq的存在,eta收缩已经不是语义保持的; 但没有匙eta收缩只能将终止程序更改为错误; 用勺子收缩可以将终止程序变成不同的终止程序。

从形式上来说, spoon不安全的一个方面是它在域上是非单调的(因此可以用它来定义函数); 而没有spoon每个功能都是单调的。 所以在技术上你会失去正式推理的有用属性。

以一个真实的例子来说明这个问题的重要性时,留给读者一个练习(阅读:我认为现实生活中不太可能重要 - 除非你开始滥用它;例如使用undefined的Java方式程序员使用null


如果这就是你所得到的,你不能用spoon写出unsafeCoerce 。 正如它看起来一样不完善,并且与看起来一样违反了Haskell语义。 但是,你不能用它来创建段错误或类似的东西。

但是,通过违反Haskell语义,它确实会使代码更难于推理,而且,例如,带有勺子的safeHead将不如直接编写的safeHead有效。

链接地址: http://www.djcxy.com/p/43231.html

上一篇: Is spoon unsafe in Haskell?

下一篇: How atomic are GHC's thunks?