module Hix.Component where import Data.List.Extra (firstJust) import qualified Data.Map.Strict as Map import Data.Map.Strict ((!?)) import qualified Data.Text as Text import Exon (exon) import Path (Abs, Dir, File, Path, Rel, SomeBase (Abs, Rel), isProperPrefixOf, reldir, stripProperPrefix) import qualified Hix.Data.ComponentConfig import Hix.Data.ComponentConfig ( ComponentConfig, PackageConfig (PackageConfig), PackageName (PackageName), PackagesConfig, SourceDir (SourceDir), Target (Target), TargetOrDefault (DefaultTarget, ExplicitTarget, NoDefaultTarget), ) import Hix.Data.Error (Error (EnvError), pathText) import Hix.Monad (M, noteEnv, throwM) import qualified Hix.Options as Options import Hix.Options ( ComponentCoords, ComponentSpec (ComponentSpec), PackageSpec (PackageSpec), TargetSpec (TargetForComponent, TargetForFile), ) import Hix.Path (rootDir) data ResolvedPackage = ResolvedPackage Bool PackageConfig | NoPackage Text deriving stock (ResolvedPackage -> ResolvedPackage -> Bool (ResolvedPackage -> ResolvedPackage -> Bool) -> (ResolvedPackage -> ResolvedPackage -> Bool) -> Eq ResolvedPackage forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: ResolvedPackage -> ResolvedPackage -> Bool == :: ResolvedPackage -> ResolvedPackage -> Bool $c/= :: ResolvedPackage -> ResolvedPackage -> Bool /= :: ResolvedPackage -> ResolvedPackage -> Bool Eq, Int -> ResolvedPackage -> ShowS [ResolvedPackage] -> ShowS ResolvedPackage -> String (Int -> ResolvedPackage -> ShowS) -> (ResolvedPackage -> String) -> ([ResolvedPackage] -> ShowS) -> Show ResolvedPackage forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> ResolvedPackage -> ShowS showsPrec :: Int -> ResolvedPackage -> ShowS $cshow :: ResolvedPackage -> String show :: ResolvedPackage -> String $cshowList :: [ResolvedPackage] -> ShowS showList :: [ResolvedPackage] -> ShowS Show, (forall x. ResolvedPackage -> Rep ResolvedPackage x) -> (forall x. Rep ResolvedPackage x -> ResolvedPackage) -> Generic ResolvedPackage forall x. Rep ResolvedPackage x -> ResolvedPackage forall x. ResolvedPackage -> Rep ResolvedPackage x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cfrom :: forall x. ResolvedPackage -> Rep ResolvedPackage x from :: forall x. ResolvedPackage -> Rep ResolvedPackage x $cto :: forall x. Rep ResolvedPackage x -> ResolvedPackage to :: forall x. Rep ResolvedPackage x -> ResolvedPackage Generic) tryPackageByDir :: PackagesConfig -> Path Rel Dir -> Maybe PackageConfig tryPackageByDir :: PackagesConfig -> Path Rel Dir -> Maybe PackageConfig tryPackageByDir PackagesConfig config Path Rel Dir dir = (PackageConfig -> Bool) -> [PackageConfig] -> Maybe PackageConfig forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find PackageConfig -> Bool match (PackagesConfig -> [PackageConfig] forall k a. Map k a -> [a] Map.elems PackagesConfig config) where match :: PackageConfig -> Bool match PackageConfig pkg = PackageConfig pkg.src Path Rel Dir -> Path Rel Dir -> Bool forall a. Eq a => a -> a -> Bool == Path Rel Dir dir packageByDir :: PackagesConfig -> Path Rel Dir -> M PackageConfig packageByDir :: PackagesConfig -> Path Rel Dir -> M PackageConfig packageByDir PackagesConfig config Path Rel Dir dir = Text -> Maybe PackageConfig -> M PackageConfig forall a. Text -> Maybe a -> M a noteEnv [exon|No package at this directory: #{pathText dir}|] (PackagesConfig -> Path Rel Dir -> Maybe PackageConfig tryPackageByDir PackagesConfig config Path Rel Dir dir) packageDefault :: Maybe PackageName -> PackagesConfig -> ResolvedPackage packageDefault :: Maybe PackageName -> PackagesConfig -> ResolvedPackage packageDefault Maybe PackageName mainPkg = \case [] -> Text -> ResolvedPackage NoPackage Text "Project has no packages." [(PackageName _, PackageConfig pkg)] -> Bool -> PackageConfig -> ResolvedPackage ResolvedPackage Bool False PackageConfig pkg PackagesConfig pkgs | Just PackageName name <- Maybe PackageName mainPkg -> case PackageName -> PackagesConfig -> Maybe PackageConfig forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup PackageName name PackagesConfig pkgs of Just PackageConfig pkg -> Bool -> PackageConfig -> ResolvedPackage ResolvedPackage Bool False PackageConfig pkg Maybe PackageConfig Nothing -> Text -> ResolvedPackage NoPackage ( [exon|Project has multiple packages and the main package '##{name}' is not among them. |] Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text "Specify -p or -f to choose one explicitly." ) PackagesConfig _ -> Text -> ResolvedPackage NoPackage Text "Project has more than one package, specify -p or -f." packageForSpec :: Path Abs Dir -> PackagesConfig -> PackageSpec -> M PackageConfig packageForSpec :: Path Abs Dir -> PackagesConfig -> PackageSpec -> M PackageConfig packageForSpec Path Abs Dir root PackagesConfig config = \case PackageSpec PackageName _ (Just (Abs Path Abs Dir dir)) -> do Path Rel Dir rel <- Text -> Maybe (Path Rel Dir) -> M (Path Rel Dir) forall a. Text -> Maybe a -> M a noteEnv [exon|Path is not a subdirectory of the project root: #{pathText dir}|] (Path Abs Dir -> Path Abs Dir -> Maybe (Path Rel Dir) forall (m :: * -> *) b t. MonadThrow m => Path b Dir -> Path b t -> m (Path Rel t) stripProperPrefix Path Abs Dir root Path Abs Dir dir) PackagesConfig -> Path Rel Dir -> M PackageConfig packageByDir PackagesConfig config Path Rel Dir rel PackageSpec (PackageName Text name) (Just (Rel Path Rel Dir dir)) | Char -> Text -> Bool Text.elem Char '/' Text name -> PackagesConfig -> Path Rel Dir -> M PackageConfig packageByDir PackagesConfig config Path Rel Dir dir PackageSpec PackageName name Maybe (SomeBase Dir) dir -> Text -> Maybe PackageConfig -> M PackageConfig forall a. Text -> Maybe a -> M a noteEnv [exon|No package matching '##{name}'|] (PackagesConfig config PackagesConfig -> PackageName -> Maybe PackageConfig forall k a. Ord k => Map k a -> k -> Maybe a !? PackageName name Maybe PackageConfig -> Maybe PackageConfig -> Maybe PackageConfig forall a. Maybe a -> Maybe a -> Maybe a forall (f :: * -> *) a. Alternative f => f a -> f a -> f a <|> (SomeBase Dir -> Maybe PackageConfig tryDir (SomeBase Dir -> Maybe PackageConfig) -> Maybe (SomeBase Dir) -> Maybe PackageConfig forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b =<< Maybe (SomeBase Dir) dir)) where tryDir :: SomeBase Dir -> Maybe PackageConfig tryDir = \case Abs Path Abs Dir _ -> Maybe PackageConfig forall a. Maybe a Nothing Rel Path Rel Dir rd -> PackagesConfig -> Path Rel Dir -> Maybe PackageConfig tryPackageByDir PackagesConfig config Path Rel Dir rd packageForSpecOrDefault :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> Maybe PackageSpec -> M ResolvedPackage packageForSpecOrDefault :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> Maybe PackageSpec -> M ResolvedPackage packageForSpecOrDefault Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config = \case Just PackageSpec pkg -> Bool -> PackageConfig -> ResolvedPackage ResolvedPackage Bool True (PackageConfig -> ResolvedPackage) -> M PackageConfig -> M ResolvedPackage forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Path Abs Dir -> PackagesConfig -> PackageSpec -> M PackageConfig packageForSpec Path Abs Dir root PackagesConfig config PackageSpec pkg Maybe PackageSpec Nothing -> ResolvedPackage -> M ResolvedPackage forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure (Maybe PackageName -> PackagesConfig -> ResolvedPackage packageDefault Maybe PackageName mainPkg PackagesConfig config) matchComponent :: ComponentConfig -> ComponentSpec -> Bool matchComponent :: ComponentConfig -> ComponentSpec -> Bool matchComponent ComponentConfig candidate (ComponentSpec ComponentName name Maybe SourceDir dir) = ComponentConfig candidate.name ComponentName -> ComponentName -> Bool forall a. Eq a => a -> a -> Bool == ComponentName name Bool -> Bool -> Bool || (SourceDir -> Bool) -> Maybe SourceDir -> Bool forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool any (\ SourceDir d -> forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool elem @[] SourceDir d (SourceDirs -> [SourceDir] forall a b. Coercible a b => a -> b coerce ComponentConfig candidate.sourceDirs)) Maybe SourceDir dir componentError :: PackageName -> ComponentSpec -> Text componentError :: PackageName -> ComponentSpec -> Text componentError PackageName pname ComponentSpec spec = [exon|No component with name or source dir '##{name}' in the package '##{pname}'|] where name :: ComponentName name = ComponentSpec spec.name undecidableComponentError :: PackageName -> Text undecidableComponentError :: PackageName -> Text undecidableComponentError PackageName pname = [exon|Please specify a component name or source dir with -c for the package '##{pname}'|] testComponent :: ComponentSpec testComponent :: ComponentSpec testComponent = ComponentName -> Maybe SourceDir -> ComponentSpec ComponentSpec ComponentName "test" (SourceDir -> Maybe SourceDir forall a. a -> Maybe a Just (Path Rel Dir -> SourceDir SourceDir [reldir|test|])) defaultComponent :: PackageConfig -> Either Text Target defaultComponent :: PackageConfig -> Either Text Target defaultComponent PackageConfig package = do ComponentConfig component <- Text -> Maybe ComponentConfig -> Either Text ComponentConfig forall l r. l -> Maybe r -> Either l r maybeToRight (PackageName -> Text undecidableComponentError PackageConfig package.name) (Map ComponentName ComponentConfig -> Maybe ComponentConfig forall {k}. Ord k => Map k ComponentConfig -> Maybe ComponentConfig selectComponent PackageConfig package.components) pure Target {$sel:sourceDir:Target :: Maybe SourceDir sourceDir = Maybe SourceDir forall a. Maybe a Nothing, PackageConfig ComponentConfig package :: PackageConfig component :: ComponentConfig $sel:package:Target :: PackageConfig $sel:component:Target :: ComponentConfig ..} where selectComponent :: Map k ComponentConfig -> Maybe ComponentConfig selectComponent [(k _, ComponentConfig comp)] = ComponentConfig -> Maybe ComponentConfig forall a. a -> Maybe a Just ComponentConfig comp selectComponent (Map k ComponentConfig -> [ComponentConfig] forall k a. Map k a -> [a] Map.elems -> [ComponentConfig] comps) = (ComponentConfig -> Bool) -> [ComponentConfig] -> Maybe ComponentConfig forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find (ComponentSpec -> ComponentConfig -> Bool match ComponentSpec testComponent) [ComponentConfig] comps match :: ComponentSpec -> ComponentConfig -> Bool match = (ComponentConfig -> ComponentSpec -> Bool) -> ComponentSpec -> ComponentConfig -> Bool forall a b c. (a -> b -> c) -> b -> a -> c flip ComponentConfig -> ComponentSpec -> Bool matchComponent targetInPackage :: ResolvedPackage -> Maybe ComponentSpec -> M TargetOrDefault targetInPackage :: ResolvedPackage -> Maybe ComponentSpec -> M TargetOrDefault targetInPackage (ResolvedPackage Bool _ PackageConfig package) (Just ComponentSpec comp) = do ComponentConfig component <- Text -> Maybe ComponentConfig -> M ComponentConfig forall a. Text -> Maybe a -> M a noteEnv (PackageName -> ComponentSpec -> Text componentError PackageConfig package.name ComponentSpec comp) ((ComponentConfig -> Bool) -> [ComponentConfig] -> Maybe ComponentConfig forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find ComponentConfig -> Bool match (Map ComponentName ComponentConfig -> [ComponentConfig] forall k a. Map k a -> [a] Map.elems PackageConfig package.components)) pure (Target -> TargetOrDefault ExplicitTarget (Target {$sel:sourceDir:Target :: Maybe SourceDir sourceDir = Maybe SourceDir forall a. Maybe a Nothing, PackageConfig ComponentConfig $sel:package:Target :: PackageConfig $sel:component:Target :: ComponentConfig package :: PackageConfig component :: ComponentConfig ..})) where match :: ComponentConfig -> Bool match ComponentConfig cand = ComponentConfig -> ComponentSpec -> Bool matchComponent ComponentConfig cand ComponentSpec comp targetInPackage (ResolvedPackage Bool True PackageConfig package) Maybe ComponentSpec Nothing = (Text -> M TargetOrDefault) -> (TargetOrDefault -> M TargetOrDefault) -> Either Text TargetOrDefault -> M TargetOrDefault forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either (Error -> M TargetOrDefault forall a. Error -> M a throwM (Error -> M TargetOrDefault) -> (Text -> Error) -> Text -> M TargetOrDefault forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error EnvError) TargetOrDefault -> M TargetOrDefault forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure (Target -> TargetOrDefault ExplicitTarget (Target -> TargetOrDefault) -> Either Text Target -> Either Text TargetOrDefault forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> PackageConfig -> Either Text Target defaultComponent PackageConfig package) targetInPackage (ResolvedPackage Bool False PackageConfig package) Maybe ComponentSpec Nothing = do (Text -> M TargetOrDefault) -> (TargetOrDefault -> M TargetOrDefault) -> Either Text TargetOrDefault -> M TargetOrDefault forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either (TargetOrDefault -> M TargetOrDefault forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure (TargetOrDefault -> M TargetOrDefault) -> (Text -> TargetOrDefault) -> Text -> M TargetOrDefault forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> TargetOrDefault NoDefaultTarget) TargetOrDefault -> M TargetOrDefault forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure (Target -> TargetOrDefault DefaultTarget (Target -> TargetOrDefault) -> Either Text Target -> Either Text TargetOrDefault forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> PackageConfig -> Either Text Target defaultComponent PackageConfig package) targetInPackage (NoPackage Text err) Maybe ComponentSpec _ = TargetOrDefault -> M TargetOrDefault forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure (Text -> TargetOrDefault NoDefaultTarget Text err) targetForComponent :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> ComponentCoords -> M TargetOrDefault targetForComponent :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> ComponentCoords -> M TargetOrDefault targetForComponent Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config ComponentCoords spec = do ResolvedPackage package <- Path Abs Dir -> Maybe PackageName -> PackagesConfig -> Maybe PackageSpec -> M ResolvedPackage packageForSpecOrDefault Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config ComponentCoords spec.package ResolvedPackage -> Maybe ComponentSpec -> M TargetOrDefault targetInPackage ResolvedPackage package ComponentCoords spec.component targetForFile :: Path Abs Dir -> PackagesConfig -> Path Abs File -> M Target targetForFile :: Path Abs Dir -> PackagesConfig -> Path Abs File -> M Target targetForFile Path Abs Dir root PackagesConfig config Path Abs File file = do Path Rel File fileRel <- Path Abs Dir -> Path Abs File -> ReaderT Env (ExceptT Error IO) (Path Rel File) forall (m :: * -> *) b t. MonadThrow m => Path b Dir -> Path b t -> m (Path Rel t) stripProperPrefix Path Abs Dir root Path Abs File file (PackageConfig package, Path Rel File subpath) <- Maybe (PackageConfig, Path Rel File) -> M (PackageConfig, Path Rel File) forall {a}. Maybe a -> M a pkgError ((PackageConfig -> Maybe (PackageConfig, Path Rel File)) -> [PackageConfig] -> Maybe (PackageConfig, Path Rel File) forall a b. (a -> Maybe b) -> [a] -> Maybe b firstJust (Path Rel File -> PackageConfig -> Maybe (PackageConfig, Path Rel File) forall {f :: * -> *} {t}. MonadThrow f => Path Rel t -> PackageConfig -> f (PackageConfig, Path Rel t) matchPackage Path Rel File fileRel) (PackagesConfig -> [PackageConfig] forall k a. Map k a -> [a] Map.elems PackagesConfig config)) (ComponentConfig component, Maybe SourceDir sourceDir) <- Maybe (ComponentConfig, Maybe SourceDir) -> M (ComponentConfig, Maybe SourceDir) forall {a}. Maybe a -> M a compError ((ComponentConfig -> Maybe (ComponentConfig, Maybe SourceDir)) -> [ComponentConfig] -> Maybe (ComponentConfig, Maybe SourceDir) forall a b. (a -> Maybe b) -> [a] -> Maybe b firstJust (Path Rel File -> ComponentConfig -> Maybe (ComponentConfig, Maybe SourceDir) forall {a} {a} {t}. (Coercible a [SourceDir], HasField "sourceDirs" a a) => Path Rel t -> a -> Maybe (a, Maybe SourceDir) matchSourceDir Path Rel File subpath) (Map ComponentName ComponentConfig -> [ComponentConfig] forall k a. Map k a -> [a] Map.elems PackageConfig package.components)) Target -> M Target forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure Target {Maybe SourceDir PackageConfig ComponentConfig $sel:sourceDir:Target :: Maybe SourceDir $sel:package:Target :: PackageConfig $sel:component:Target :: ComponentConfig package :: PackageConfig component :: ComponentConfig sourceDir :: Maybe SourceDir ..} where matchPackage :: Path Rel t -> PackageConfig -> f (PackageConfig, Path Rel t) matchPackage Path Rel t fileRel package :: PackageConfig package@PackageConfig {Path Rel Dir src :: Path Rel Dir $sel:src:PackageConfig :: PackageConfig -> Path Rel Dir src} = do Path Rel t subpath <- Path Rel Dir -> Path Rel t -> f (Path Rel t) forall (m :: * -> *) b t. MonadThrow m => Path b Dir -> Path b t -> m (Path Rel t) stripProperPrefix Path Rel Dir src Path Rel t fileRel pure (PackageConfig package, Path Rel t subpath) matchSourceDir :: Path Rel t -> a -> Maybe (a, Maybe SourceDir) matchSourceDir Path Rel t subpath a component = do let match :: SourceDir -> Maybe SourceDir match d :: SourceDir d@(SourceDir Path Rel Dir dir) = if Path Rel Dir -> Path Rel t -> Bool forall b t. Path b Dir -> Path b t -> Bool isProperPrefixOf Path Rel Dir dir Path Rel t subpath then SourceDir -> Maybe SourceDir forall a. a -> Maybe a Just SourceDir d else Maybe SourceDir forall a. Maybe a Nothing SourceDir dir <- (SourceDir -> Maybe SourceDir) -> [SourceDir] -> Maybe SourceDir forall a b. (a -> Maybe b) -> [a] -> Maybe b firstJust SourceDir -> Maybe SourceDir match (a -> [SourceDir] forall a b. Coercible a b => a -> b coerce a component.sourceDirs) pure (a component, SourceDir -> Maybe SourceDir forall a. a -> Maybe a Just SourceDir dir) pkgError :: Maybe a -> M a pkgError = Text -> Maybe a -> M a forall a. Text -> Maybe a -> M a noteEnv Text "No package contains this file" compError :: Maybe a -> M a compError = Text -> Maybe a -> M a forall a. Text -> Maybe a -> M a noteEnv Text "No component source dir contains this file" targetComponentIn :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponentIn :: Path Abs Dir -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponentIn Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config = \case TargetForComponent ComponentCoords spec -> Path Abs Dir -> Maybe PackageName -> PackagesConfig -> ComponentCoords -> M TargetOrDefault targetForComponent Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config ComponentCoords spec TargetForFile Path Abs File spec -> Target -> TargetOrDefault ExplicitTarget (Target -> TargetOrDefault) -> M Target -> M TargetOrDefault forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Path Abs Dir -> PackagesConfig -> Path Abs File -> M Target targetForFile Path Abs Dir root PackagesConfig config Path Abs File spec targetComponent :: Maybe (Path Abs Dir) -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponent :: Maybe (Path Abs Dir) -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponent Maybe (Path Abs Dir) cliRoot Maybe PackageName mainPkg PackagesConfig config TargetSpec spec = do Path Abs Dir root <- Maybe (Path Abs Dir) -> M (Path Abs Dir) rootDir Maybe (Path Abs Dir) cliRoot Path Abs Dir -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponentIn Path Abs Dir root Maybe PackageName mainPkg PackagesConfig config TargetSpec spec targetComponentOrError :: Maybe (Path Abs Dir) -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M Target targetComponentOrError :: Maybe (Path Abs Dir) -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M Target targetComponentOrError Maybe (Path Abs Dir) cliRoot Maybe PackageName mainPkg PackagesConfig config TargetSpec spec = Maybe (Path Abs Dir) -> Maybe PackageName -> PackagesConfig -> TargetSpec -> M TargetOrDefault targetComponent Maybe (Path Abs Dir) cliRoot Maybe PackageName mainPkg PackagesConfig config TargetSpec spec M TargetOrDefault -> (TargetOrDefault -> M Target) -> M Target forall a b. ReaderT Env (ExceptT Error IO) a -> (a -> ReaderT Env (ExceptT Error IO) b) -> ReaderT Env (ExceptT Error IO) b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case ExplicitTarget Target t -> Target -> M Target forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure Target t DefaultTarget Target t -> Target -> M Target forall a. a -> ReaderT Env (ExceptT Error IO) a forall (f :: * -> *) a. Applicative f => a -> f a pure Target t NoDefaultTarget Text err -> Error -> M Target forall a. Error -> M a throwM (Text -> Error EnvError Text err)