Skip to content

Instantly share code, notes, and snippets.

@parsonsmatt
Created November 29, 2022 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parsonsmatt/0102d73a38a583b05cc13833d62135d7 to your computer and use it in GitHub Desktop.
Save parsonsmatt/0102d73a38a583b05cc13833d62135d7 to your computer and use it in GitHub Desktop.
How to redefine functions in Haskell, based on Hillel's article here: https://buttondown.email/hillelwayne/archive/i-am-disappointed-by-dynamic-typing/
{-# language BangPatterns #-}
module MutDef where
import Data.IORef
import System.IO.Unsafe
import Data.Map (Map)
import qualified Data.Map as Map
import GHC.Exts
{-# NOINLINE doubleImpl #-}
doubleImpl :: IORef (Int -> Int)
doubleImpl = unsafePerformIO $ do
newIORef (\x -> x * 2)
double :: Int -> Int
double i = unsafePerformIO $ do
impl <- readIORef doubleImpl
pure (impl i)
{-# NOINLINE double #-}
g :: Int -> Int
g x = double (double x) + double x
main = do
print (g 2)
-- 12
calledArgs <- newIORef mempty :: IO (IORef (Map Int Int))
modifyIORef' doubleImpl $ \f !i ->
unsafePerformIO $ do
modifyIORef' calledArgs (Map.insertWith (+) i 1)
pure (f i)
print (g 2)
-- 12
print =<< readIORef calledArgs
-- fromList [(2,1),(4,1)]
redefineDouble :: ((Int -> Int) -> Int -> Int) -> IO ()
redefineDouble withOldFn =
modifyIORef' doubleImpl $ \f !i ->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment