[英]Haskell / GHC: Unsafely deconstruct a constructor?
这是我真正问的一般问题的具体情况:假设我处于性能关键的代码部分并且我收到了一个值
x :: Maybe Int
我知道这是一个Just Int
而不是Nothing
,但由于代码不受控制,我无法安排直接接收实际的Int
。 我想要做
case x of
Just i -> whatever i
但我不希望GHC插入任何检查或错误处理或跳转或任何东西; 只是将这些位解释为好像它们是Just i
的形式,并让我处理后果。
这可能吗? (是的,我知道这是不应该经常做的事情。)
考虑使用YOLO
类型类https://gist.github.com/nkpart/8922083d3c18a8f777b8
instance Yolo Maybe where
yolo (Just x) = x
NB:那是个玩笑。 使用fromJust
。
有时您可以通过添加一些模式签名来帮助GHC确定GADT模式匹配是完全的。 我不确定为什么这有时会有所帮助,但它可以。 如果你真的想要不安全,那么做到这一点的方法就是制作一个比你正在使用的更加信息丰富的GADT并且不安全地强迫它。 像这样的东西:
data Shmaybe :: Bool -> * -> * where
Noway :: Shmaybe r a
Shucks :: a -> Shmaybe True a
fromShucks :: ShMaybe True a -> a
fromShucks (Shucks a) = a
unsafeFromJust :: forall a . Maybe a -> a
unsafeFromJust m = fromShucks (unsafeCoerce m :: Shmaybe True a)
构造函数在参数类型和顺序中都匹配很重要。 显然,这都是荒谬的不安全,并没有任何保证。 可能发生分段错误。
我知道几种可能性,但所有隐含的包含在Nothing
案例中抛出错误的代码。
无可辩驳的模式 :
λ> let Just a = Just "hi"
λ> a
"hi"
λ> let Just a = Nothing
λ> a
*** Exception: <interactive>:4:5-20: Irrefutable pattern failed for pattern Data.Maybe.Just a
非穷尽模式 :
λ> let f (Just a) = a
λ> f (Just "hi")
"hi"
λ> f Nothing
*** Exception: <interactive>:6:5-18: Non-exhaustive patterns in function f
fromJust
(检查并抛出错误):
λ> fromJust (Just "hi")
"hi"
λ> fromJust Nothing
*** Exception: Maybe.fromJust: Nothing
不能使用unsafeCoerce
,因为所有的a
内部表示Maybe a
和a
是不同的,我不知道的方式告诉GHC不检查的其他情形的一个无可辩驳的模式。
您是否表明此行为具有不良的性能特征,并且没有其他更容易的优化? 除非你有,我不担心它:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.