Here's a specific case of the general question I'm really asking: Suppose I'm in a performance critical section of code and I've received a value
x :: Maybe Int
I know it's a Just Int
and not a Nothing
, but due to code out of my control, I can't arrange to receive the actual Int
directly. I want to do
case x of
Just i -> whatever i
but I don't want GHC to insert any checking or error handling or jumps or anything; just interpret the bits as if they are of the form Just i
and let me deal with the consequences.
Is this possible? (Yes, I know this is something one shouldn't do regularly.)
Sometimes you can help GHC figure out that a GADT pattern match is total by adding some pattern signatures. I'm not really sure why that sometimes helps but it can. If you really want unsafe, the way to do it is to make a more informative GADT than the one you are working with and unsafely coerce to it. Something like this:
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)
It's important that the constructors match in both argument types and order. Obviously, this is all absurdly unsafe and comes with no guarantees. Segmentation faults may happen.
Consider using the YOLO
typeclass
https://gist.github.com/nkpart/8922083d3c18a8f777b8
instance Yolo Maybe where
yolo (Just x) = x
N.B: That was a joke. Use fromJust
.
I am aware of several possibilities, but all implicitly include code for
throwing errors in the Nothing
case.
Irrefutable pattern:
λ> 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
Non-exhastive patterns:
λ> let f (Just a) = a
λ> f (Just "hi")
"hi"
λ> f Nothing
*** Exception: <interactive>:6:5-18: Non-exhaustive patterns in function f
fromJust
(check and throw error):
λ> fromJust (Just "hi")
"hi"
λ> fromJust Nothing
*** Exception: Maybe.fromJust: Nothing
You cannot use unsafeCoerce
because for all a
the internal representations of Maybe a
and a
are different, and I am
not aware of a way to tell GHC to not check the other cases in
an irrefutable pattern.
Have you shown that this behaviour has undesirable performance characteristics and that there aren't other, easier optimisations? Unless you have, I would not worry about it :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With