Skip to content

Commit 669cfe3

Browse files
committed
Fix #404: add evalState(T)
Use case: stateful interpreter (`eval`) for C-like expressions `e`: ```haskell let Ur value = HashMap.empty capacity (\ env -> move (evalState (eval e) env)) ``` This pattern breaks the "jail" set by the type signature of `HashMap`-allocation: ```haskell empty :: Int -> (HashMap k v %1 -> Ur b) %1 -> Ur b ``` `HashMap` is not `Movable` but `Consumable`, so we can get rid of it before `move`ing the result to `Ur`.
1 parent 46566eb commit 669cfe3

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

src/Control/Functor/Linear.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@ module Control.Functor.Linear
4848
State,
4949
state,
5050
runState,
51+
evalState,
5152
execState,
5253
mapState,
5354
withState,
5455
StateT (..),
5556
runStateT,
57+
evalStateT,
5658
execStateT,
5759
mapStateT,
5860
withStateT,

src/Control/Functor/Linear/Internal/State.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module Control.Functor.Linear.Internal.State
2121
runState,
2222
mapStateT,
2323
mapState,
24+
evalStateT,
25+
evalState,
2426
execStateT,
2527
execState,
2628
withStateT,
@@ -36,6 +38,7 @@ import qualified Control.Monad.Trans.State.Strict as NonLinear
3638
import Data.Functor.Identity
3739
import qualified Data.Functor.Linear.Internal.Applicative as Data
3840
import qualified Data.Functor.Linear.Internal.Functor as Data
41+
import qualified Data.Tuple.Linear as Linear
3942
import Data.Unrestricted.Linear.Internal.Consumable
4043
import Data.Unrestricted.Linear.Internal.Dupable
4144
import Prelude.Linear.Internal
@@ -80,6 +83,11 @@ withStateT r (StateT f) = StateT (f . r)
8083
execStateT :: Functor m => StateT s m () %1 -> s %1 -> m s
8184
execStateT f = fmap (\((), s) -> s) . (runStateT f)
8285

86+
-- | Use with care!
87+
-- This consumes the final state, so might be costly at runtime.
88+
evalStateT :: (Functor m, Consumable s) => StateT s m a %1 -> s %1 -> m a
89+
evalStateT f = fmap Linear.fst . runStateT f
90+
8391
mapState :: ((a, s) %1 -> (b, s)) %1 -> State s a %1 -> State s b
8492
mapState f = mapStateT (Identity . f . runIdentity')
8593

@@ -89,6 +97,11 @@ withState = withStateT
8997
execState :: State s () %1 -> s %1 -> s
9098
execState f = runIdentity' . execStateT f
9199

100+
-- | Use with care!
101+
-- This consumes the final state, so might be costly at runtime.
102+
evalState :: Consumable s => State s a %1 -> s %1 -> a
103+
evalState f = runIdentity' . evalStateT f
104+
92105
modify :: Applicative m => (s %1 -> s) %1 -> StateT s m ()
93106
modify f = state $ \s -> ((), f s)
94107

src/Data/Tuple/Linear.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module Data.Tuple.Linear
1212
where
1313

1414
import Data.Unrestricted.Linear.Internal.Consumable
15-
import Prelude.Linear.Internal ( curry, uncurry )
15+
import Prelude.Linear.Internal (curry, uncurry)
1616

1717
fst :: Consumable b => (a, b) %1 -> a
1818
fst (a, b) = lseq b a

0 commit comments

Comments
 (0)