cro*_*eea 7 monads haskell impredicativetypes
我想要类似的东西
f :: [forall m. (Mutable v) (PrimState m) r -> m ()] -> v r -> v r -- illegal signature
f gs x = runST $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs -- you get the idea
unsafeFreeze y
Run Code Online (Sandbox Code Playgroud)
在Vitus评论的这个问题中,我基本上处于同样的位置:
[I]如果你想在某些结构中保留多态函数,你需要专门的数据类型(例如newtype I = I(forall a.a - > a))或ImpredicativeTypes.
另外,请看这个问题.问题是,这些都是非常难看的解决方案.所以我提出了第三种选择,即通过运行"应该"作为ST计算IO来完全避免多态性.因此f成为:
f :: [(Mutable v) RealWorld r -> IO ()] -> v r -> v r
f gs x = unsafePerformIO $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs -- you get the idea
unsafeFreeze y
Run Code Online (Sandbox Code Playgroud)
unsafe IO与"安全"路线相比,我觉得去路线有点脏ST,但如果我的替代方案是包装或不可预测的类型......显然,我并不孤单.
我有什么理由不在unsafePerformIO这里使用吗?在这种情况下,它真的不安全吗?是否存在性能因素或其他我应该注意的事项?
- - - - - - - 编辑 - - - - - - - -
下面的答案告诉我如何彻底解决这个问题,这很好.但是我仍然对原始问题(使用可变载体时的runSTvs的含义unsafePerformIO)用于教育目的感兴趣.
我不能说我完全理解了问题陈述,但是下面的文件在GHC 7.6.2下编译没有错误.它与你的第一个例子具有相同的身体(特别是根本不打电话unsafePerformIO); 主要区别在于forall移动到所有类型构造函数之外.
{-# LANGUAGE RankNTypes #-}
import Control.Monad
import Control.Monad.Primitive (PrimState)
import Control.Monad.ST
import Data.Vector.Generic hiding (foldM_)
f :: Vector v r => (forall m. [Mutable v (PrimState m) r -> m ()]) -> v r -> v r
f gs x = runST $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs
unsafeFreeze y
Run Code Online (Sandbox Code Playgroud)
现在让我们解决STvs IO问题.它被调用的原因unsafePerformIO并不是unusablePerformIO因为它带有编译器无法检查的证明负担:您运行的东西unsafePerformIO必须表现得好像它是引用透明的.由于ST操作带有(编译器检查的)证据,证明它们在执行时行为透明runST,这意味着使用unsafePerformIO代码时不会ST有比使用中更严重的危险runST.
但是:从软件工程的角度来看存在危险.由于证明不再经过编译器检查,因此未来的重构更容易违反安全使用的条件unsafePerformIO.因此,如果可以避免它(因为它似乎在这里),你应该努力这样做.(此外,"没有更多的危险"并不意味着"没有危险":unsafeFreeze您正在进行的呼叫有其必须满足的证明负担;但是您已经必须满足ST代码的证明负担是对的.)
| 归档时间: |
|
| 查看次数: |
258 次 |
| 最近记录: |