commit 99272a8cfadf876e5a5630cb638b85c2ca6c1296
parent a6a71f9862a4f3706e9b0f5955c9db2d67037565
Author: Robert Russell <robert@rr3.xyz>
Date: Thu, 15 Oct 2026 17:57:25 -0700
Error: add better exception-throwing util functions
Diffstat:
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/src/Lude/Error.hs b/src/Lude/Error.hs
@@ -1,7 +1,5 @@
module Lude.Error (
- assert,
- error,
- undefined,
+ module X,
--
ErrorMessage,
ErrText,
@@ -9,12 +7,20 @@ module Lude.Error (
type (!||),
type (!//),
TypeError,
+ --
+ panic,
+ impossible,
+ --
+ unimplemented,
+ todo,
) where
-import Control.Exception (assert)
-import Prelude (error, undefined)
+-- NOTE: `assert` is special (GHC can compile assertions to no-ops based on
+-- a CLI flag), so we export it directly.
+import Control.Exception as X (assert)
import GHC.TypeError qualified as GHC
+import Prelude qualified as Base
import Lude.Haskell
@@ -43,3 +49,32 @@ type (!//) = (GHC.:$$:)
-- | Produce a custom type error
type TypeError :: forall k. ErrorMessage -> k
type TypeError msg = GHC.TypeError msg
+
+--------------------------------------------------------------------------------
+
+type PanicExn :: Type
+newtype PanicExn = MkPanicExn Base.String
+ deriving stock (Base.Show)
+instance Exception PanicExn where
+ displayException (MkPanicExn msg) = "panic: " Base.++ msg
+
+panic :: forall {r :: Repr} (a :: Type# r). (HasCallStack) => Base.String -> a
+panic msg = withFrozenCallStack (unsafe_raise (MkPanicExn msg))
+
+impossible :: forall {r :: Repr} (a :: Type# r). (HasCallStack) => a
+impossible = withFrozenCallStack (panic "impossible")
+
+--------------------------------------------------------------------------------
+
+type UnimplementedExn :: Type
+newtype UnimplementedExn = MkUnimplementedExn Base.String
+ deriving stock (Base.Show)
+instance Exception UnimplementedExn where
+ displayException (MkUnimplementedExn msg) = "unimplemented: " Base.++ msg
+
+unimplemented :: forall {r :: Repr} (a :: Type# r). (HasCallStack) => Base.String -> a
+unimplemented msg = withFrozenCallStack (unsafe_raise (MkUnimplementedExn msg))
+
+todo :: forall {r :: Repr} (a :: Type# r). (HasCallStack) => a
+todo = withFrozenCallStack (unimplemented "todo")
+{-# WARNING in "x-todo" todo "todo left in code" #-}