mirror of
https://github.com/zap-proto/haskell.git
synced 2026-10-30 15:05:00 +00:00
68 lines
1.7 KiB
Haskell
68 lines
1.7 KiB
Haskell
{-# LANGUAGE DeriveDataTypeable #-}
|
|
{-# LANGUAGE DerivingStrategies #-}
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
{-# LANGUAGE RankNTypes #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
-- | Simplified implementation of the monad-ste package,
|
|
-- with a few extras.
|
|
module Internal.STE
|
|
( STE,
|
|
throwSTE,
|
|
runSTE,
|
|
liftST,
|
|
steToST,
|
|
steToIO,
|
|
)
|
|
where
|
|
|
|
import Control.Exception
|
|
import Control.Monad.Catch (MonadThrow (..))
|
|
import Control.Monad.Primitive (PrimMonad (..))
|
|
import Control.Monad.ST
|
|
import Control.Monad.ST.Unsafe
|
|
import Data.Typeable (Typeable)
|
|
|
|
newtype InternalErr e = InternalErr e
|
|
deriving stock (Typeable)
|
|
|
|
instance Show (InternalErr e) where
|
|
show _ = "(InternalErr _)"
|
|
|
|
instance Typeable e => Exception (InternalErr e)
|
|
|
|
newtype STE e s a = STE (IO a)
|
|
deriving newtype (Functor, Applicative, Monad)
|
|
|
|
instance PrimMonad (STE e s) where
|
|
type PrimState (STE e s) = s
|
|
primitive = liftST . primitive
|
|
|
|
liftST :: ST s a -> STE e s a
|
|
liftST st = STE (unsafeSTToIO st)
|
|
|
|
throwSTE :: Exception e => e -> STE e s a
|
|
throwSTE e = STE (throwIO (InternalErr e))
|
|
|
|
runSTE :: Exception e => (forall s. STE e s a) -> Either e a
|
|
runSTE ste = runST (steToST ste)
|
|
|
|
steToST :: Typeable e => STE e s a -> ST s (Either e a)
|
|
steToST (STE io) = unsafeIOToST $ do
|
|
res <- try io
|
|
case res of
|
|
Left (InternalErr e) -> pure $ Left e
|
|
Right v -> pure $ Right v
|
|
|
|
steToIO :: forall e a. Exception e => STE e RealWorld a -> IO a
|
|
steToIO (STE io) = do
|
|
res <- try io
|
|
case res of
|
|
Left (InternalErr (e :: e)) -> throwIO e
|
|
Right v -> pure v
|
|
|
|
instance MonadThrow (STE SomeException s) where
|
|
throwM = throwSTE . toException
|