Quick actions

cmd+k|ctrl+k

Navigation

Languages

ST monad in unsafe but pure Haskell

Snippet info

Language

Haskell

Visibility

public

Author

740243525

Created

2019-09-25T10:38:19Z

Updated

2020-03-25T03:45:47Z

{-# LANGUAGE MultiParamTypeClasses,RankNTypes #-}
import Control.Monad
import Data.IORef
import System.IO.Unsafe
newtype MyST s a=MyST {toIO :: IO a}
newtype MySTRef s a=MySTRef {toIORef :: IORef a} deriving Eq

instance Monad (MyST s) where
    return x=MyST $ return x
    a >>= f=MyST $ do
        val<-toIO a
        toIO $ f val
instance Functor (MyST s) where
    fmap=liftM
instance Applicative (MyST s) where
    pure=return
    (<*>)=ap

newMySTRef :: a->MyST s (MySTRef s a)
newMySTRef x=MyST $ do
    ref<-newIORef x
    return $ MySTRef ref

readMySTRef :: MySTRef s a->MyST s a
readMySTRef ref=MyST $ readIORef $ toIORef ref

writeMySTRef :: MySTRef s a->a->MyST s ()
writeMySTRef ref x=MyST $ do
    writeIORef (toIORef ref) x
    return ()
modifyMySTRef :: MySTRef s a->(a->a)->MyST s ()
modifyMySTRef ref f=do
    val<-readMySTRef ref
    writeMySTRef ref (f val)

-- The signature prevents MySTRef leak.
runMyST :: forall a.(forall s. MyST s a)->a
-- a cat dies.
runMyST = unsafePerformIO . toIO

leakingRunMyST :: (MyST s a)->a
leakingRunMyST = unsafePerformIO . toIO

leakInt :: Int->MySTRef s Int
leakInt = leakingRunMyST . newMySTRef

badEquation = (leakInt 3) == (leakInt 3)


prog=do
    ref<-newMySTRef "hello"
    x<-readMySTRef ref
    writeMySTRef ref (x++"world")
    readMySTRef ref

--leak_ref=do
--    ref<-newMySTRef "leak!"
--    return ref

--use_leak_ref =runMyST $ do
--    readMySTRef (runMyST leak_ref)


main=(print $ runMyST prog) >> print badEquation
INFO