Skip to content

Commit

Permalink
Implement lazy using unsafeDupablePerformIO
Browse files Browse the repository at this point in the history
This might be faster than using an IORef, though I don't notice any
difference when measuring. The API should be safe even though it's
implemented using unsafe functions.

Ref. #2.
  • Loading branch information
ollef committed Apr 6, 2020
1 parent f7b0e9d commit afd15ee
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/Domain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Var (Var)
data Value
= Neutral !Head Spine
| Lit !Literal
| Glued !Head Spine !(Lazy Value)
| Glued !Head Spine (Lazy Value)
| Lam !Name !Type !Plicity !Closure
| Pi !Name !Type !Plicity !Closure
| Fun !Type !Plicity !Type
Expand Down
26 changes: 15 additions & 11 deletions src/Monad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ module Monad where

import Protolude hiding (try, State)

import Control.Monad.Base
import Data.IORef.Lifted
import Control.Monad.Trans.Control
import Control.Exception.Lifted
import Rock
import System.IO.Unsafe (unsafeDupablePerformIO)

import qualified Error
import Query (Query)
Expand All @@ -19,19 +20,22 @@ newtype State = State
{ nextVar :: IORef Var
}

newtype Lazy a = Lazy { force :: M a }
newtype Lazy a = Lazy a

lazy :: MonadBase IO m => M a -> m (Lazy a)
lazy m = do
ref <- newIORef $ panic "Can't happen, I promise!"
writeIORef ref $ do
result <- m
writeIORef ref $ pure result
pure result
pure $ Lazy $ join $ readIORef ref
{-# inline force #-}
force :: Lazy a -> M a
force (Lazy a) =
a `seq` pure a

{-# inline lazy #-}
lazy :: M a -> M (Lazy a)
lazy m =
liftBaseWith $ \runInIO ->
pure $ Lazy $ unsafeDupablePerformIO $ runInIO m

eager :: a -> Lazy a
eager = Lazy . pure
eager =
Lazy

freshVar :: M Var
freshVar = do
Expand Down

0 comments on commit afd15ee

Please sign in to comment.