Skip to content

Instantly share code, notes, and snippets.

@TerrorJack
Created December 30, 2022 18:24
Show Gist options
  • Save TerrorJack/94841d52157f4912bc669ed9cea4f639 to your computer and use it in GitHub Desktop.
Save TerrorJack/94841d52157f4912bc669ed9cea4f639 to your computer and use it in GitHub Desktop.
Unpacked Maybe type in Haskell
import Maybe
main :: IO ()
main = do
print $ myJust "23333"
print (myNothing :: MyMaybe ())
-- | Unpacked 'Maybe' type by @TerrorJack. Tested with -O0 and ghci
-- -fobject-code in GHC-9.4.4. Heavily inspired by
-- https://twitter.com/AndreasK_Tweets/status/1545112873290153991,
-- with a improvement: Laziness is preserved when calling the 'myJust'
-- smart constructor. The thunk is only forced when calling 'isJust'
-- (we have to, since 'MyMaybe' is lifted and may be a thunk that
-- evaluates to 'myNothing' in the end).
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE UnliftedFFITypes #-}
module Maybe
( MyMaybe,
myJust,
myNothing,
isJust,
fromJust,
)
where
import GHC.Exts
newtype MyMaybe a = MyMaybe {fromJust :: a}
instance Show a => Show (MyMaybe a) where
show v
| isJust v = "Just " <> show (fromJust v)
| otherwise = "Nothing"
myJust :: a -> MyMaybe a
myJust = MyMaybe
myNothing :: MyMaybe a
myNothing = unsafeCoerce# nothing#
isJust :: MyMaybe a -> Bool
isJust !v = case isJust# (unsafeCoerce# v) of
0# -> False
_ -> True
foreign import prim "stg_Nothingzh" nothing# :: Any
foreign import prim "stg_isJustzh" isJust# :: Any -> Int#
#include "Cmm.h"
import CLOSURE stg_dummy_ret_closure;
stg_Nothingzh () {
return (stg_dummy_ret_closure);
}
stg_isJustzh (P_ val) {
if (val == stg_dummy_ret_closure) {
return (0);
} else {
return (1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment