module Unison.Prelude
  ( module X,
    readUtf8,
    safeReadUtf8,
    safeReadUtf8StdIn,
    writeUtf8,
    prependUtf8,
    uncurry4,
    reportBug,
    tShow,
    wundefined,

    -- * @Bool@ control flow
    onFalse,
    onFalseM,
    onTrue,
    onTrueM,

    -- * @Maybe@ control flow
    onNothing,
    onNothingM,
    whenNothing,
    whenNothingM,
    whenJust,
    whenJustM,
    eitherToMaybe,
    maybeToEither,
    altSum,
    altMap,
    hoistMaybe,

    -- * @Either@ control flow
    onLeft,
    onLeftM,
    whenLeft,
    whenLeftM,
    throwEitherM,
    throwEitherMWith,
    throwExceptT,
    throwExceptTWith,

    -- * Basic lensy stuff we use all over
    (^.),
    (.~),
    (%~),
    view,
    set,
    over,
  )
where

import Control.Applicative as X
import Control.Category as X ((>>>))
import Control.Exception as X (Exception, IOException, SomeException)
import Control.Lens (over, set, view, (%~), (.~), (^.))
import Control.Monad as X
import Control.Monad.Extra as X (ifM, mapMaybeM, unlessM, whenM)
import Control.Monad.IO.Class as X (MonadIO (liftIO))
import Control.Monad.Trans as X (MonadTrans (lift))
import Control.Monad.Trans.Except (ExceptT (ExceptT), runExceptT, withExceptT)
import Control.Monad.Trans.Maybe as X (MaybeT (MaybeT, runMaybeT))
import Data.Bifunctor as X (Bifunctor (..))
import Data.ByteString as X (ByteString)
import Data.Coerce as X (Coercible, coerce)
import Data.Either as X
import Data.Either.Combinators as X (mapLeft, maybeToRight)
import Data.Either.Extra (eitherToMaybe, maybeToEither)
import Data.Foldable as X (fold, foldl', for_, toList, traverse_)
import Data.Function as X ((&))
import Data.Functor as X
import Data.Functor.Identity as X
-- #labelSyntax for generics-derived lenses
import Data.Generics.Labels ()
import Data.Int as X
import Data.List as X (foldl1', sortOn)
import Data.Map as X (Map)
import Data.Maybe as X (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, maybeToList)
import Data.Sequence as X (Seq)
import Data.Set as X (Set)
import Data.String as X (IsString, fromString)
import Data.Text as X (Text)
import Data.Text qualified as Text
import Data.Text.Encoding as X (decodeUtf8, encodeUtf8)
import Data.Text.IO qualified as Text
import Data.Traversable as X (for)
import Data.Typeable as X (Typeable)
import Data.Void as X (Void)
import Data.Word as X
import Debug.Trace as X
import GHC.Generics as X (Generic, Generic1)
import GHC.IO.Handle qualified as Handle
import GHC.Stack as X (HasCallStack)
import Safe as X (atMay, headMay, lastMay, readMay)
import System.Directory qualified as Directory
import System.FilePath qualified as FilePath
import System.IO qualified as IO
import Text.Read as X (readMaybe)
import UnliftIO as X (MonadUnliftIO (..), askRunInIO, askUnliftIO, try, withUnliftIO)
import UnliftIO qualified
import UnliftIO.Directory qualified as UnliftIO
import Witch as X (From (from), TryFrom (tryFrom), TryFromException (TryFromException), into, tryInto)
import Witherable as X (filterA, forMaybe, mapMaybe, wither, witherMap)

-- | Can be removed when we upgrade transformers to a more recent version.
hoistMaybe :: (Applicative m) => Maybe a -> MaybeT m a
hoistMaybe :: forall (m :: * -> *) a. Applicative m => Maybe a -> MaybeT m a
hoistMaybe = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a)
-> (Maybe a -> m (Maybe a)) -> Maybe a -> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | Like 'fold' but for Alternative.
altSum :: (Alternative f, Foldable t) => t (f a) -> f a
altSum :: forall (f :: * -> *) (t :: * -> *) a.
(Alternative f, Foldable t) =>
t (f a) -> f a
altSum = (f a -> f a -> f a) -> f a -> t (f a) -> f a
forall b a. (b -> a -> b) -> b -> t a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' f a -> f a -> f a
forall a. f a -> f a -> f a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) f a
forall a. f a
forall (f :: * -> *) a. Alternative f => f a
empty

-- | Like 'foldMap' but for Alternative.
altMap :: (Alternative f, Foldable t) => (a -> f b) -> t a -> f b
altMap :: forall (f :: * -> *) (t :: * -> *) a b.
(Alternative f, Foldable t) =>
(a -> f b) -> t a -> f b
altMap a -> f b
f = [f b] -> f b
forall (f :: * -> *) (t :: * -> *) a.
(Alternative f, Foldable t) =>
t (f a) -> f a
altSum ([f b] -> f b) -> (t a -> [f b]) -> t a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f b) -> [a] -> [f b]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> f b
f ([a] -> [f b]) -> (t a -> [a]) -> t a -> [f b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t a -> [a]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- |
-- > condition & onFalse do
-- >   shortCircuit
onFalse :: (Applicative m) => m () -> Bool -> m ()
onFalse :: forall (m :: * -> *). Applicative m => m () -> Bool -> m ()
onFalse m ()
action = \case
  Bool
False -> m ()
action
  Bool
True -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- |
-- > action & onFalseM do
-- >   shortCircuit
onFalseM :: (Monad m) => m () -> m Bool -> m ()
onFalseM :: forall (m :: * -> *). Monad m => m () -> m Bool -> m ()
onFalseM m ()
x m Bool
y =
  m Bool
y m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m () -> Bool -> m ()
forall (m :: * -> *). Applicative m => m () -> Bool -> m ()
onFalse m ()
x

-- |
-- > condition & onTrue do
-- >   shortCircuit
onTrue :: (Applicative m) => m () -> Bool -> m ()
onTrue :: forall (m :: * -> *). Applicative m => m () -> Bool -> m ()
onTrue m ()
action = \case
  Bool
True -> m ()
action
  Bool
False -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- |
-- > action & onTrueM do
-- >   shortCircuit
onTrueM :: (Monad m) => m () -> m Bool -> m ()
onTrueM :: forall (m :: * -> *). Monad m => m () -> m Bool -> m ()
onTrueM m ()
x m Bool
y =
  m Bool
y m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m () -> Bool -> m ()
forall (m :: * -> *). Applicative m => m () -> Bool -> m ()
onTrue m ()
x

-- | E.g.
--
-- @@
-- onNothing (throwIO MissingPerson) $ mayThing
-- @@
onNothing :: (Applicative m) => m a -> Maybe a -> m a
onNothing :: forall (m :: * -> *) a. Applicative m => m a -> Maybe a -> m a
onNothing m a
m Maybe a
may = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
m a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
may

onNothingM :: (Monad m) => m a -> m (Maybe a) -> m a
onNothingM :: forall (m :: * -> *) a. Monad m => m a -> m (Maybe a) -> m a
onNothingM =
  (m (Maybe a) -> m a -> m a) -> m a -> m (Maybe a) -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip m (Maybe a) -> m a -> m a
forall (m :: * -> *) a. Monad m => m (Maybe a) -> m a -> m a
whenNothingM

-- | E.g. @maybePerson `whenNothing` throwIO MissingPerson@
whenNothing :: (Applicative m) => Maybe a -> m a -> m a
whenNothing :: forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
whenNothing Maybe a
may m a
m = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
m a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
may

whenNothingM :: (Monad m) => m (Maybe a) -> m a -> m a
whenNothingM :: forall (m :: * -> *) a. Monad m => m (Maybe a) -> m a -> m a
whenNothingM m (Maybe a)
mx m a
my =
  m (Maybe a)
mx m (Maybe a) -> (Maybe a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
my a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

whenJust :: (Applicative m) => Maybe a -> (a -> m ()) -> m ()
whenJust :: forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust Maybe a
mx a -> m ()
f =
  m () -> (a -> m ()) -> Maybe a -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) a -> m ()
f Maybe a
mx

whenJustM :: (Monad m) => m (Maybe a) -> (a -> m ()) -> m ()
whenJustM :: forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> (a -> m ()) -> m ()
whenJustM m (Maybe a)
mx a -> m ()
f = do
  m (Maybe a)
mx m (Maybe a) -> (Maybe a -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m () -> (a -> m ()) -> Maybe a -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) a -> m ()
f

onLeft :: (Applicative m) => (a -> m b) -> Either a b -> m b
onLeft :: forall (m :: * -> *) a b.
Applicative m =>
(a -> m b) -> Either a b -> m b
onLeft =
  (Either a b -> (a -> m b) -> m b)
-> (a -> m b) -> Either a b -> m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip Either a b -> (a -> m b) -> m b
forall (m :: * -> *) a b.
Applicative m =>
Either a b -> (a -> m b) -> m b
whenLeft

onLeftM :: (Monad m) => (a -> m b) -> m (Either a b) -> m b
onLeftM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> m (Either a b) -> m b
onLeftM =
  (m (Either a b) -> (a -> m b) -> m b)
-> (a -> m b) -> m (Either a b) -> m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip m (Either a b) -> (a -> m b) -> m b
forall (m :: * -> *) a b.
Monad m =>
m (Either a b) -> (a -> m b) -> m b
whenLeftM

whenLeft :: (Applicative m) => Either a b -> (a -> m b) -> m b
whenLeft :: forall (m :: * -> *) a b.
Applicative m =>
Either a b -> (a -> m b) -> m b
whenLeft = \case
  Left a
a -> \a -> m b
f -> a -> m b
f a
a
  Right b
b -> \a -> m b
_ -> b -> m b
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
b

whenLeftM :: (Monad m) => m (Either a b) -> (a -> m b) -> m b
whenLeftM :: forall (m :: * -> *) a b.
Monad m =>
m (Either a b) -> (a -> m b) -> m b
whenLeftM m (Either a b)
m a -> m b
f =
  m (Either a b)
m m (Either a b) -> (Either a b -> m b) -> m b
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left a
x -> a -> m b
f a
x
    Right b
y -> b -> m b
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
y

throwExceptT :: (MonadIO m, Exception e) => ExceptT e m a -> m a
throwExceptT :: forall (m :: * -> *) e a.
(MonadIO m, Exception e) =>
ExceptT e m a -> m a
throwExceptT = (e -> e) -> ExceptT e m a -> m a
forall (m :: * -> *) e' e a.
(MonadIO m, Exception e') =>
(e -> e') -> ExceptT e m a -> m a
throwExceptTWith e -> e
forall a. a -> a
id

throwExceptTWith :: (MonadIO m, Exception e') => (e -> e') -> ExceptT e m a -> m a
throwExceptTWith :: forall (m :: * -> *) e' e a.
(MonadIO m, Exception e') =>
(e -> e') -> ExceptT e m a -> m a
throwExceptTWith e -> e'
f ExceptT e m a
action =
  ExceptT e' m a -> m (Either e' a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT ((e -> e') -> ExceptT e m a -> ExceptT e' m a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT e -> e'
f ExceptT e m a
action) m (Either e' a) -> (Either e' a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left e'
e -> IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> (e' -> IO a) -> e' -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e' -> IO a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
UnliftIO.throwIO (e' -> m a) -> e' -> m a
forall a b. (a -> b) -> a -> b
$ e'
e
    Right a
a -> a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

throwEitherM :: forall e m a. (MonadIO m, Exception e) => m (Either e a) -> m a
throwEitherM :: forall e (m :: * -> *) a.
(MonadIO m, Exception e) =>
m (Either e a) -> m a
throwEitherM = (e -> e) -> m (Either e a) -> m a
forall e e' (m :: * -> *) a.
(MonadIO m, Exception e') =>
(e -> e') -> m (Either e a) -> m a
throwEitherMWith e -> e
forall a. a -> a
id

throwEitherMWith :: forall e e' m a. (MonadIO m, Exception e') => (e -> e') -> m (Either e a) -> m a
throwEitherMWith :: forall e e' (m :: * -> *) a.
(MonadIO m, Exception e') =>
(e -> e') -> m (Either e a) -> m a
throwEitherMWith e -> e'
f m (Either e a)
action = ExceptT e' m a -> m a
forall (m :: * -> *) e a.
(MonadIO m, Exception e) =>
ExceptT e m a -> m a
throwExceptT (ExceptT e' m a -> m a)
-> (ExceptT e m a -> ExceptT e' m a) -> ExceptT e m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (e -> e') -> ExceptT e m a -> ExceptT e' m a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT e -> e'
f (ExceptT e m a -> m a) -> ExceptT e m a -> m a
forall a b. (a -> b) -> a -> b
$ (m (Either e a) -> ExceptT e m a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT m (Either e a)
action)

tShow :: (Show a) => a -> Text
tShow :: forall a. Show a => a -> Text
tShow = String -> Text
Text.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show

-- | Strictly read an entire file decoding UTF8.
-- Converts \r\n -> \n on windows.
readUtf8 :: FilePath -> IO Text
readUtf8 :: String -> IO Text
readUtf8 String
fileName =
  String -> IOMode -> (Handle -> IO Text) -> IO Text
forall (m :: * -> *) a.
MonadUnliftIO m =>
String -> IOMode -> (Handle -> m a) -> m a
UnliftIO.withFile String
fileName IOMode
UnliftIO.ReadMode Handle -> IO Text
readUtf8Handle

-- | Strictly read from a handle, decoding UTF8, or failing if not valid UTF8
-- Converts \r\n -> \n on windows.
safeReadUtf8 :: FilePath -> IO (Either IOException Text)
safeReadUtf8 :: String -> IO (Either IOException Text)
safeReadUtf8 String
p = IO Text -> IO (Either IOException Text)
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (String -> IO Text
readUtf8 String
p)

-- | Strictly read from a handle, decoding UTF8.
-- Note, this changes the newline-mode of the handle
-- to convert \r\n -> \n on windows.
readUtf8Handle :: IO.Handle -> IO Text
readUtf8Handle :: Handle -> IO Text
readUtf8Handle Handle
handle = do
  Handle -> TextEncoding -> IO ()
Handle.hSetEncoding Handle
handle TextEncoding
IO.utf8
  Handle -> IO Text
Text.hGetContents Handle
handle

-- | Strictly read from stdin, decoding UTF8.
-- Converts \r\n -> \n on windows.
safeReadUtf8StdIn :: IO (Either IOException Text)
safeReadUtf8StdIn :: IO (Either IOException Text)
safeReadUtf8StdIn = do
  Handle
handle <- Handle -> IO Handle
Handle.hDuplicate Handle
IO.stdin
  IO Text -> IO (Either IOException Text)
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (IO Text -> IO (Either IOException Text))
-> IO Text -> IO (Either IOException Text)
forall a b. (a -> b) -> a -> b
$ Handle -> IO Text
readUtf8Handle Handle
handle

uncurry4 :: (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
uncurry4 :: forall a b c d e. (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
uncurry4 a -> b -> c -> d -> e
f (a
a, b
b, c
c, d
d) =
  a -> b -> c -> d -> e
f a
a b
b c
c d
d

-- | Write a file strictly assuming UTF8
-- Converts \n -> \r\n on windows.
writeUtf8 :: FilePath -> Text -> IO ()
writeUtf8 :: String -> Text -> IO ()
writeUtf8 String
fileName Text
txt = do
  String -> IOMode -> (Handle -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadUnliftIO m =>
String -> IOMode -> (Handle -> m a) -> m a
UnliftIO.withFile String
fileName IOMode
UnliftIO.WriteMode ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Handle
handle -> do
    Handle -> TextEncoding -> IO ()
Handle.hSetEncoding Handle
handle TextEncoding
IO.utf8
    Handle -> Text -> IO ()
Text.hPutStr Handle
handle Text
txt

-- | Atomically prepend some text to a file, creating the file if it doesn't already exist
prependUtf8 :: FilePath -> Text -> IO ()
prependUtf8 :: String -> Text -> IO ()
prependUtf8 String
path Text
txt = do
  String -> IO Bool
Directory.doesFileExist String
path IO Bool -> (Bool -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Bool
False -> String -> Text -> IO ()
writeUtf8 String
path Text
txt
    Bool
True -> do
      let withTempFile :: String -> Handle -> IO ()
withTempFile String
tmpFilePath Handle
tmpHandle = do
            Handle -> TextEncoding -> IO ()
Handle.hSetEncoding Handle
tmpHandle TextEncoding
IO.utf8
            Handle -> Text -> IO ()
Text.hPutStrLn Handle
tmpHandle Text
txt
            String -> IOMode -> (Handle -> IO ()) -> IO ()
forall r. String -> IOMode -> (Handle -> IO r) -> IO r
IO.withFile String
path IOMode
IO.ReadMode \Handle
currentScratchFile -> do
              Handle -> TextEncoding -> IO ()
Handle.hSetEncoding Handle
currentScratchFile TextEncoding
IO.utf8
              let copyLoop :: IO ()
copyLoop = do
                    Text
chunk <- Handle -> IO Text
Text.hGetChunk Handle
currentScratchFile
                    case Text -> Int
Text.length Text
chunk Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 of
                      Bool
True -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                      Bool
False -> do
                        Handle -> Text -> IO ()
Text.hPutStr Handle
tmpHandle Text
chunk
                        IO ()
copyLoop
              IO ()
copyLoop
            Handle -> IO ()
IO.hClose Handle
tmpHandle
            String -> String -> IO ()
forall (m :: * -> *). MonadIO m => String -> String -> m ()
UnliftIO.renameFile String
tmpFilePath String
path
      String -> String -> (String -> Handle -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadUnliftIO m =>
String -> String -> (String -> Handle -> m a) -> m a
UnliftIO.withTempFile (String -> String
FilePath.takeDirectory String
path) String
".unison-scratch" String -> Handle -> IO ()
withTempFile

reportBug :: String -> String -> String
reportBug :: String -> String -> String
reportBug String
bugId String
msg =
  [String] -> String
unlines
    [ String
"🐞",
      String
"",
      String
msg,
      String
"",
      String
"This is a Unison bug and you can report it here:",
      String
"",
      String
"https://github.com/unisonweb/unison/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
bugId String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"+",
      String
"",
      String
"Bug reference: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
bugId,
      String
"",
      String
"If there's already an issue with this reference, you can give a 👍",
      String
"on the issue to let the team know you encountered it, and you can add",
      String
"any additional details you know of to the issue."
    ]

{-# WARNING wundefined "You left this wundefined." #-}
wundefined :: (HasCallStack) => a
wundefined :: forall a. HasCallStack => a
wundefined = a
forall a. HasCallStack => a
undefined