|
| 1 | +module DebuggingLog.Main where |
| 2 | + |
| 3 | +import Prelude |
| 4 | + |
| 5 | +import Control.Monad.ST.Internal as ST |
| 6 | +import Data.Tuple (Tuple(..)) |
| 7 | +import Debug.Trace (spy, traceM) |
| 8 | +import Effect (Effect) |
| 9 | +import Effect.Aff (launchAff_) |
| 10 | +import Effect.Class (liftEffect) |
| 11 | +import Effect.Console (log) |
| 12 | + |
| 13 | +data MyADT = MyADT Int (Tuple Int (Array String)) { foo :: String } |
| 14 | + |
| 15 | +main :: Effect Unit |
| 16 | +main = do |
| 17 | + log "When we are in the 'Effect' monad, we can print content to the console." |
| 18 | + launchAff_ do |
| 19 | + liftEffect $ log $ "We can still print values to the console as long as \ |
| 20 | + \the monad in question implements the MonadEffect \ |
| 21 | + \type class. Since `Aff` implements MonadEffect, we \ |
| 22 | + \can lift that effect into `Aff`." |
| 23 | + |
| 24 | + log "However, there are times when we want to debug some code and wish \ |
| 25 | + \to use print-based debugging. Since PureScript is pure, how do we \ |
| 26 | + \do that?" |
| 27 | + |
| 28 | + usingSpy |
| 29 | + |
| 30 | + usingTraceM |
| 31 | + |
| 32 | + compareSpyAndTraceM |
| 33 | + |
| 34 | +usingSpy :: Effect Unit |
| 35 | +usingSpy = do |
| 36 | + log "usingSpy" |
| 37 | + -- `spy` returns the value it receives. However, it prints that value |
| 38 | + -- to the console before it "returns." |
| 39 | + -- spy :: forall a. DebugWarning => String -> a -> a |
| 40 | + -- You can use this in a `let` clause pretty reliably |
| 41 | + let |
| 42 | + x = 5 |
| 43 | + y = spy "y" 8 |
| 44 | + adt = spy "adt" $ MyADT 1 (Tuple 4 ["a", "b"]) { foo: "foo value" } |
| 45 | + function = spy "function" $ \intValue -> show $ 4 + intValue |
| 46 | + |
| 47 | + -- quick way of debugging something without showing it or using a |
| 48 | + -- variable name |
| 49 | + _ = spy "debug for me what x + y is" $ x + y |
| 50 | + arrayOfStrings = spy "debug some array" $ map show [1, 2, 3, 4, 5] |
| 51 | + |
| 52 | + -- quickly drop-in `spy` to see every step of a recursive function |
| 53 | + fact :: Int -> Int -> Int |
| 54 | + fact 0 acc = acc |
| 55 | + fact n acc = fact (spy "n" (n - 1)) (spy "acc" (acc * n)) |
| 56 | + |
| 57 | + _ = fact 5 1 |
| 58 | + |
| 59 | + log $ "Thus, spying is an effective way of quickly adding debugging where \ |
| 60 | + \you need it without affecting any other part of your code. \ |
| 61 | + \Note: you should not use `spy` to do logging in production code. \ |
| 62 | + \Use a proper logger in production code." |
| 63 | + |
| 64 | +usingTraceM :: Effect Unit |
| 65 | +usingTraceM = do |
| 66 | + log "usingTraceM" |
| 67 | + traceM "Notice how this text's color is different than what is outputted \ |
| 68 | + \via `log`." |
| 69 | + |
| 70 | + let |
| 71 | + localMutationComputation |
| 72 | + :: forall ensureMutationStaysLocal. ST.ST ensureMutationStaysLocal Int |
| 73 | + localMutationComputation = do |
| 74 | + -- the ST monad does not implement `MonadEffect`, |
| 75 | + -- so `traceM` is the only way to log output to the console in a |
| 76 | + -- `log`-like fashion. |
| 77 | + localReference <- ST.new 0 |
| 78 | + traceM localReference |
| 79 | + four <- ST.modify (_ + 4) localReference |
| 80 | + traceM four |
| 81 | + ST.write (four + 2) localReference |
| 82 | + |
| 83 | + log $ "Local reference value is: " <> show (ST.run localMutationComputation) |
| 84 | + |
| 85 | +compareSpyAndTraceM :: Effect Unit |
| 86 | +compareSpyAndTraceM = do |
| 87 | + let x = 5 |
| 88 | + _ = spy "x" x |
| 89 | + traceM x |
0 commit comments