Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Debug.Trace.Linear #174

Merged
merged 1 commit into from
Sep 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions linear-base.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ library
Data.Profunctor.Linear
Data.Profunctor.Kleisli.Linear
Data.Unrestricted.Linear
Debug.Trace.Linear
Foreign.Marshal.Pure
Prelude.Linear
System.IO.Linear
Expand Down
92 changes: 92 additions & 0 deletions src/Debug/Trace/Linear.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}

{-|
A thin wrapper on top of "Debug.Trace", providing linear versions of
tracing functions.

It only contains minimal amount of documentation; you should consult
the original "Debug.Trace" module for more detailed information.
-}
module Debug.Trace.Linear
( -- * Tracing
trace
, traceShow
, traceId
, traceStack
, traceIO
, traceM
, traceShowM
-- * Eventlog tracing
, traceEvent
, traceEventIO
-- * Execution phase markers
, traceMarker
, traceMarkerIO
) where

import qualified Debug.Trace as NonLinear
import qualified Unsafe.Linear as Unsafe
import System.IO.Linear
import Data.Functor.Linear
import Data.Unrestricted.Linear
import Prelude (String, Show(..))
import Prelude.Linear.Internal

-- | The 'trace' function outputs the trace message given as its first
-- argument, before returning the second argument as its result.
trace :: String #-> a #-> a
trace = Unsafe.toLinear2 NonLinear.trace

-- | Like 'trace', but uses 'show' on the argument to convert it to
-- a 'String'.
traceShow :: Show a => a -> b #-> b
traceShow a = Unsafe.toLinear (NonLinear.traceShow a)

-- | Like 'trace' but returns the message instead of a third value.
traceId :: String #-> String
traceId s = dup s & \(s', s'') -> trace s' s''

-- | Like 'trace', but additionally prints a call stack if one is
-- available.
traceStack :: String #-> a #-> a
traceStack = Unsafe.toLinear2 NonLinear.traceStack

-- | The 'traceIO' function outputs the trace message from the IO monad.
-- This sequences the output with respect to other IO actions.
traceIO :: String #-> IO ()
traceIO s = fromSystemIO (Unsafe.toLinear NonLinear.traceIO s)

-- | Like 'trace' but returning unit in an arbitrary 'Applicative'
-- context. Allows for convenient use in do-notation.
traceM :: Applicative f => String #-> f ()
traceM s = trace s $ pure ()

-- | Like 'traceM', but uses 'show' on the argument to convert it to a
-- 'String'.
traceShowM :: (Show a, Applicative f) => a -> f ()
traceShowM a = traceM (show a)

-- | The 'traceEvent' function behaves like 'trace' with the difference
-- that the message is emitted to the eventlog, if eventlog profiling is
-- available and enabled at runtime.
traceEvent :: String #-> a #-> a
traceEvent = Unsafe.toLinear2 NonLinear.traceEvent

-- | The 'traceEventIO' function emits a message to the eventlog, if
-- eventlog profiling is available and enabled at runtime.
traceEventIO :: String #-> IO ()
traceEventIO s = fromSystemIO (Unsafe.toLinear NonLinear.traceEventIO s)

-- | The 'traceMarker' function emits a marker to the eventlog, if eventlog
-- profiling is available and enabled at runtime. The @String@ is the name
-- of the marker. The name is just used in the profiling tools to help you
-- keep clear which marker is which.
traceMarker :: String #-> a #-> a
traceMarker = Unsafe.toLinear2 NonLinear.traceMarker

-- | The 'traceMarkerIO' function emits a marker to the eventlog, if
-- eventlog profiling is available and enabled at runtime.
traceMarkerIO :: String #-> IO ()
traceMarkerIO s = fromSystemIO (Unsafe.toLinear NonLinear.traceMarkerIO s)