packages feed

hierarchical-env 0.1.0.0 → 0.2.0.0

raw patch · 8 files changed

+193/−119 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Env.Hierarchical: data Root
- Control.Env.Hierarchical.Internal: instance (Control.Env.Hierarchical.Internal.Field s' s, Control.Env.Hierarchical.Internal.Trans a l s') => Control.Env.Hierarchical.Internal.Trans a (s : l) s
- Control.Env.Hierarchical.Internal: instance Control.Env.Hierarchical.Internal.Trans a '[] a
- Control.Env.Hierarchical.Internal: type (<:) env env' = Trans env' (Addr env env') env
+ Control.Env.Hierarchical: --
+ Control.Env.Hierarchical: -- </ul>
+ Control.Env.Hierarchical: -- <li>Every <tt>env</tt> must have at most one field of the form
+ Control.Env.Hierarchical: -- <li>If <tt>env</tt> owns no field of the form <tt><a>Extends</a>
+ Control.Env.Hierarchical: -- <tt>Extends T</tt> because multiple inheritance is not supported.</li>
+ Control.Env.Hierarchical: -- <ul>
+ Control.Env.Hierarchical: -- T</tt>, then <a>Root</a> is the super environment.</li>
+ Control.Env.Hierarchical: -- environments.
+ Control.Env.Hierarchical: Extends :: env -> Extends env
+ Control.Env.Hierarchical: class Environment env where {
+ Control.Env.Hierarchical: newtype Extends env
+ Control.Env.Hierarchical: superL :: (Environment env, Field (Extends (Super env)) env) => Lens' env (Super env)
+ Control.Env.Hierarchical.Internal: --
+ Control.Env.Hierarchical.Internal: -- </ul>
+ Control.Env.Hierarchical.Internal: -- <li>Every <tt>env</tt> must have at most one field of the form
+ Control.Env.Hierarchical.Internal: -- <li>If <tt>env</tt> owns no field of the form <tt><a>Extends</a>
+ Control.Env.Hierarchical.Internal: -- <tt>Extends T</tt> because multiple inheritance is not supported.</li>
+ Control.Env.Hierarchical.Internal: -- <ul>
+ Control.Env.Hierarchical.Internal: -- T</tt>, then <a>Root</a> is the super environment.</li>
+ Control.Env.Hierarchical.Internal: -- environments.
+ Control.Env.Hierarchical.Internal: Extends :: env -> Extends env
+ Control.Env.Hierarchical.Internal: extendsL :: Lens' (Extends x) x
+ Control.Env.Hierarchical.Internal: instance (Control.Env.Hierarchical.Internal.Environment s, Control.Env.Hierarchical.Internal.Super s GHC.Types.~ t, Control.Env.Hierarchical.Internal.Trans t l) => Control.Env.Hierarchical.Internal.Trans s (t : l)
+ Control.Env.Hierarchical.Internal: instance Control.Env.Hierarchical.Internal.Trans s '[]
+ Control.Env.Hierarchical.Internal: newtype Extends env
+ Control.Env.Hierarchical.Internal: rootL :: Lens' x Root
+ Control.Env.Hierarchical.Internal: superL :: (Environment env, Field (Extends (Super env)) env) => Lens' env (Super env)
- Control.Env.Hierarchical.Internal: class Trans a (l :: [Type]) s | a l -> s
+ Control.Env.Hierarchical.Internal: class Trans s (l :: [Type]) where {
- Control.Env.Hierarchical.Internal: transL :: Trans a l s => Lens' s a
+ Control.Env.Hierarchical.Internal: transL :: Trans s l => Lens' s (Target s l)

Files

CHANGELOG.md view
@@ -1,5 +1,23 @@ # Revision history for hierarchical-env +## 0.2.0.0 -- 2021-04-28+* Change how to specify the super environment+  * Before: Specify by adding type instance for `Super env`+    +    ```haskell+    data Env = Env !BaseEnv !Int+    deriveEnv ''Env+    type instance Super Env = BaseEnv+    ```+  * After: Wrapping the super environment field with `Extends`++    ```haskell+    data Env = Env !(Extends BaseEnv) !Int+    deriveEnv ''Env+    ```+* Fix the type error bug occurs when hiding dependencies.++ ## 0.1.0.0 -- 2021-04-22  * First version. Released on an unsuspecting world.
hierarchical-env.cabal view
@@ -5,10 +5,11 @@ -- http://haskell.org/cabal/users-guide/  name:               hierarchical-env-version:            0.1.0.0+version:            0.2.0.0 synopsis:           hierarchical environments for dependency injection+description:+  This library provides scalable dependency injection for RIO monad -description:        This library provides scalable dependency injection for RIO monad homepage:           https://github.com/autotaker/hierarchical-env  -- bug-reports:@@ -18,7 +19,7 @@ maintainer:         autotaker@gmail.com  -- copyright:-category: Control+category:           Control extra-source-files:   CHANGELOG.md   README.md@@ -31,7 +32,7 @@     , microlens-mtl     ^>=0.2     , microlens-th      ^>=0.4     , rio               >=0.1.16.0-    , template-haskell  >=2.15 && < 2.18+    , template-haskell  >=2.15     && <2.18     , th-abstraction    ^>=0.4.2.0    default-language: Haskell2010
src/Control/Env/Hierarchical.hs view
@@ -24,8 +24,8 @@      -- ** With hierarchical environments     -- $usage:hierarchical-    Root,-    Super,+    Environment (Super, superL),+    Extends (Extends),     deriveEnv,      -- * Hiding dependencies@@ -36,10 +36,10 @@ where  import Control.Env.Hierarchical.Internal-  ( Has,+  ( Environment (Super, superL),+    Extends (Extends),+    Has,     Has1,-    Root,-    Super,     getL,     runIF,   )@@ -103,7 +103,6 @@ -- -- @ -- 'deriveEnv' ''Env--- type instance 'Super' Env = 'Root' -- @ -- -- Now, you can inject dependency by specifying the actual value of @Env@@@ -125,7 +124,7 @@  -- $usage:hierarchical -- Instead of resolving the dependency universally,--- you can extend environments by specifying the super environment.+-- you can extend environments by adding @Extend T@ as a field. -- -- In the following example @ExtEnv@ inherits @BaseEnv@. -- The extended environment is a nominal sub-type of its super environment,@@ -138,12 +137,10 @@ -- data BaseEnv = BaseEnv !ServerName !ConnectionPool -- -- 'deriveEnv' ''BaseEnv--- type instance 'Super' BaseEnv = 'Root' ----- data ExtEnv = ExtEnv !BaseEnv !(UserRepo ExtEnv)+-- data ExtEnv = ExtEnv !(Extends BaseEnv) !(UserRepo ExtEnv) -- -- 'deriveEnv' ''ExtEnv--- type instance 'Super' ExtEnv = BaseEnv -- @ -- -- Then, @ExtEnv@ resolves the dependencies.@@ -158,7 +155,7 @@ -- runApp :: ServerName -> ConnectionPool -> [UserName] -> IO () -- runApp serverName pool users = do --   let baseEnv = BaseEnv serverName pool---       extEnv = ExtEnv baseEnv userRepoImpl+--       extEnv = ExtEnv (Extends baseEnv) userRepoImpl --   runRIO extEnv $ do --     printServerName --     forM_ users $ \usernm -> do@@ -214,12 +211,11 @@ -- instance 'Interface' AuthHandler where --   type 'IBase' AuthHandler = RIO ----- data AuthEnv env = AuthEnv !(UserRepo (AutheEnv env)) !env+-- data AuthEnv env = AuthEnv !(UserRepo (AutheEnv env)) !(Extends env) -- 'deriveEnv' ''AuthEnv--- type instance 'Super' (AuthEnv env) = env -- -- authHandlerImpl :: ('Has' ConnectionPool env) => AuthHandler env--- authHandlerImpl = 'mapBaseRIO' (AuthEnv userRepoImpl) handler+-- authHandlerImpl = 'mapBaseRIO' (AuthEnv userRepoImpl . Extends) handler --   where --     handler = AuthHandler signinImpl signupImpl -- @
src/Control/Env/Hierarchical/Internal.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}@@ -21,17 +22,18 @@ -- Stability: experimental module Control.Env.Hierarchical.Internal   ( Environment (..),-    Super,+    Extends (..),     Root (..),     Field (..),     Trans (..),-    type (<:),     SomeInterface (SomeInterface),     Has,     Has1,     getL,     ifaceL,     runIF,+    rootL,+    extendsL,   ) where @@ -45,25 +47,44 @@ import Lens.Micro.Mtl (view) import RIO (RIO, runRIO) --- | @Super env@ represents the inheritance relation between environments.--- Every environment must be a descendant of 'Root'.-type family Super env- class Environment env where+  -- | @Super env@ represents the inheritance relation between environments.+  --+  -- * If @env@ owns a field of the form @'Extends' T@, then @T@ is the super environment.+  -- * If @env@ owns no field of the form @'Extends' T@, then 'Root' is the super environment.+  -- * Every @env@ must have at most one field of the form @Extends T@ because multiple inheritance is not supported.+  type Super env+   -- | interfaces that are fields of the environment   type Fields1 env :: [Type -> Type]    -- | fields of the environment   type Fields env :: [Type] +  -- | Lens to super environment+  superL :: Lens' env (Super env)+  {-# INLINE superL #-}+  default superL :: Field (Extends (Super env)) env => Lens' env (Super env)+  superL = fieldL . extendsL+ -- | Root environment that does not have any fields. data Root = Root -type instance Super Root = TypeError ('Text "No super environment for Root")+-- | Wrapper that represents the super environment.+newtype Extends env = Extends env +{-# INLINE extendsL #-}+extendsL :: Lens' (Extends x) x+extendsL f (Extends x) = fmap Extends (f x)++rootL :: Lens' x Root+rootL f x = x <$ f Root+ instance Environment Root where+  type Super Root = TypeError ('Text "No super environment for Root")   type Fields1 Root = '[]   type Fields Root = '[]+  superL = undefined  -- | direct field of @env@ class Field a env where@@ -72,40 +93,53 @@ instance Field env env where   fieldL = id -class Trans a (l :: [Type]) s | a l -> s where-  transL :: Lens' s a+-- Addr s t = '[v1, ... vn]+-- s = v1 <: v2 <: ... <: vn = t+-- s = env1 <: env2 <: env3 = Target s '[env2, env3]+-- s = env1 <: env2 = Target s '[env2]+-- s = env1 = Target s '[]+-- Trans env1 [env1]+class Trans s (l :: [Type]) where+  type Target s l+  transL :: Lens' s (Target s l) -instance Trans a '[] a where+instance Trans s '[] where+  type Target s '[] = s   transL = id -instance (Field s' s, Trans a l s') => Trans a (s : l) s where-  transL = fieldL . transL @a @l+instance (Environment s, Super s ~ t, Trans t l) => Trans s (t : l) where+  type Target s (t : l) = Target t l+  transL = superL . transL @t @l -type family Addr a b :: [Type] where-  Addr a a = '[]-  Addr a b = a : Addr (Super a) b+-- env1 <: env2 <: env3+-- Addr env1 env3 = [env2, env3]+-- Addr env2 env3 = [env3]+-- Addr env3 env3 = []+type family Addr a :: [Type] where+  Addr Root = '[]+  Addr a = Super a ': Addr (Super a)  type family Member (f :: k) (l :: [k]) :: Bool where   Member f '[] = 'False   Member f (f : l) = 'True   Member f (g : l) = Member f l -type family FindEnv (f :: Type) (envs :: [Type]) where-  FindEnv f (env ': envs) = If (Member f (Fields env)) env (FindEnv f envs)-  FindEnv f '[] = TypeError ('Text "No environment has " ':<>: 'ShowType f)--type family FindEnv1 (f :: Type -> Type) (envs :: [Type]) where-  FindEnv1 f (env ': envs) = If (Member f (Fields1 env)) env (FindEnv1 f envs)-  FindEnv1 f '[] = TypeError ('Text "No environment has " ':<>: 'ShowType f)+-- X <- Env1, FindEnv X Env1 [Env2,Root] => []+-- X <- Env2, FindEnv X Env1 [Env2,Root] => [Env2]+type family FindEnv (f :: Type) env (envs :: [Type]) :: [Type] where+  FindEnv f env (env' ': envs) = If (Member f (Fields env)) '[] (env' : FindEnv f env' envs)+  FindEnv f env '[] = TypeError ('Text "No environment has " ':<>: 'ShowType f) -type (<:) env env' = Trans env' (Addr env env') env+type family FindEnv1 (f :: Type -> Type) env (envs :: [Type]) :: [Type] where+  FindEnv1 f env (env' ': envs) = If (Member f (Fields1 env)) '[] (env' : FindEnv1 f env' envs)+  FindEnv1 f env '[] = TypeError ('Text "No environment has " ':<>: 'ShowType f)  data SomeInterface f env where   SomeInterface :: Lens' env' (f env') -> Lens' env env' -> SomeInterface f env -type HasAux a env env' = (env <: env', Field a env')+type HasAux a env route = (Trans env route, Field a (Target env route)) -type Has1Aux f env env' = (env <: env', Field (f env') env')+type Has1Aux f env route = (Trans env route, Field (f (Target env route)) (Target env route))  -- | Type constraint meaning @env@ contains @a@ as a (including ancestors') field. --@@ -113,23 +147,21 @@ -- @Has T env@. If you want to depends on multiple values of the same type, -- please distinguish them by using newtype. type family Has a env where-  Has a env = HasAux a env (FindEnv a (Ancestors env))+  Has a env = HasAux a env (FindEnv a env (Addr env))  -- | Type constraint meaning @env@ contains @f env'@ for some ancestor @env'@ type family Has1 f env where-  Has1 f env = Has1Aux f env (FindEnv1 f (Ancestors env))--type Ancestors env = Addr env Root--inheritL :: forall env env'. env <: env' => Lens' env env'-inheritL = transL @env' @(Addr env env')+  Has1 f env = Has1Aux f env (FindEnv1 f env (Addr env))  -- | Lens to extract @a@ from @env@ getL :: forall a env. Has a env => Lens' env a-getL = inheritL @env @(FindEnv a (Ancestors env)) . fieldL+getL = transL @env @(FindEnv a env (Addr env)) . fieldL  ifaceL :: forall f env. Has1 f env => SomeInterface f env-ifaceL = SomeInterface (fieldL @(f (FindEnv1 f (Ancestors env)))) inheritL+ifaceL =+  SomeInterface+    (fieldL @(f (Target env (FindEnv1 f env (Addr env)))))+    (transL @env @(FindEnv1 f env (Addr env)))  -- | Run action that depends on an interface @f@. -- The action must be polymorphic to @env'@,@@ -137,7 +169,7 @@ runIF :: forall f env a. Has1 f env => (forall env'. f env' -> RIO env' a) -> RIO env a runIF body =   case ifaceL @f of-    SomeInterface _ifaceL superL -> do-      iface <- view $ superL . _ifaceL-      env <- view superL+    SomeInterface _ifaceL _superL -> do+      iface <- view $ _superL . _ifaceL+      env <- view _superL       runRIO env (body iface)
src/Control/Env/Hierarchical/TH.hs view
@@ -10,10 +10,13 @@ module Control.Env.Hierarchical.TH (deriveEnv) where  import Control.Env.Hierarchical.Internal-  ( Environment (Fields, Fields1),+  ( Environment (Fields, Fields1, Super, superL),+    Extends,     Field (fieldL),+    Root,+    rootL,   )-import Control.Monad (filterM, zipWithM)+import Control.Monad (filterM, guard, zipWithM) import Data.Function ((&)) import Language.Haskell.TH   ( Dec (TySynD),@@ -44,44 +47,16 @@     promotedConsT,     promotedNilT,     reify,+    reportError,     reportWarning,     tySynEqn,     tySynInstD,+    valD,     varE,     varP,   ) import qualified Language.Haskell.TH.Datatype as D--{--data Env f a b = Env {-    _x :: Int,-    _y :: a,-    _z :: Obj Env,-    _w :: Obj2 b Env-    _v :: f Env--}-deriveEnvironment ''Env-==>-instance Environment (Env f a b) where-    type Fields (Env f a b) = '[Env f a b, Int, a,Obj Env, Obj2 b Env, f Env]-    type Fields1 (Env f a b) = '[Obj, Obj2 b, f]--instance Field Int (Env f a b) where-  fieldL = x--instance Field a (Env f a b) where-  fieldL = y--instance Field (Obj Env) (Env f a b) where-  fieldL = z--instance Field (Obj2 b Env) (Env f a b) where-  fieldL = w--instance Field (f Env) (Env f a b) where-  fieldL = v--}+import Language.Haskell.TH.Ppr (commaSep)  deriveEnv :: Name -> Q [Dec] deriveEnv envName = do@@ -139,7 +114,7 @@     envTypeQ = pure envType     -- envType = D.datatypeType info     decs :: [DecQ]-    decs = [fieldsDec, fields1Dec]+    decs = [fieldsDec, fields1Dec, superDec] ++ [superLDec | null extendsT]     -- tyVars = D.datatypeVars info     -- type Fields ($envName $typeVars) = '[$field1 ... $field2]     fieldsDec = tySynInstD (tySynEqn (Just tyVars) lhs rhs)@@ -151,6 +126,26 @@       where         lhs = conT ''Fields1 `appT` envTypeQ         rhs = promotedListT =<< fields1 envType consInfo++    -- Super ($envName $typeVars) = $t+    -- where @$Extends $t@ is a field of the environment+    superDec = tySynInstD (tySynEqn (Just tyVars) lhs rhs)+      where+        lhs = conT ''Super `appT` envTypeQ+        rhs = case extendsT of+          [t] -> pure t+          [] -> conT ''Root+          ts@(t : _) -> do+            reportError $ "Multiple inheritance is not allowed: " <> show (commaSep ts)+            pure t+    extendsT :: [Type]+    extendsT = do+      AppT (ConT conName) t <- D.constructorFields consInfo+      guard $ conName == ''Extends+      pure t++    -- superL = rootL (only if @Super ($envName $typeVars) = Root@)+    superLDec = valD (varP 'superL) (normalB (varE 'rootL)) []  fields1 :: Type -> D.ConstructorInfo -> Q [Type] fields1 ty consInfo =
test/Control/Env/Hierarchical/InternalSpec.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}@@ -8,13 +10,17 @@ module Control.Env.Hierarchical.InternalSpec where  import Control.Env.Hierarchical.Internal-  ( Environment (Fields, Fields1),+  ( Environment (Fields, Fields1, superL),+    Extends (Extends),     Field (fieldL),-    Root,+    Has,+    Root (Root),     Super,     getL,     runIF,   )+import Control.Method (Interface (IBase), mapBaseRIO)+import GHC.Generics (Generic) import Lens.Micro.Mtl (view) import Lens.Micro.TH (makeLenses) import RIO (RIO, runRIO)@@ -40,6 +46,9 @@ newtype Param2 = Param2 Int   deriving (Eq, Show) +newtype Param3 = Param3 Int+  deriving (Eq, Show)+ data Env1 = Env1   { _obj1 :: Obj1 Env1,     _param1 :: Param1@@ -48,7 +57,7 @@ makeLenses ''Env1  data Env2 = Env2-  { _env1 :: Env1,+  { _env1 :: Extends Env1,     _obj2 :: Obj2 Env2,     _param2 :: Param2   }@@ -58,17 +67,13 @@ instance Environment Env1 where   type Fields1 Env1 = '[Obj1]   type Fields Env1 = '[Env1, Obj1 Env1, Param1]--type instance Super Env1 = Root+  type Super Env1 = Root+  superL f x = x <$ f Root  instance Environment Env2 where   type Fields1 Env2 = '[Obj2]-  type Fields Env2 = '[Env2, Env1, Obj2 Env2, Param2]--type instance Super Env2 = Env1--instance Field Env1 Env1 where-  fieldL = id+  type Fields Env2 = '[Extends Env1, Obj2 Env2, Param2]+  type Super Env2 = Env1  instance Field (Obj1 Env1) Env1 where   fieldL = obj1@@ -76,10 +81,7 @@ instance Field Param1 Env1 where   fieldL = param1 -instance Field Env2 Env2 where-  fieldL = id--instance Field Env1 Env2 where+instance Field (Extends Env1) Env2 where   fieldL = env1  instance Field (Obj2 Env2) Env2 where@@ -111,9 +113,35 @@             _method4 = pure 4           },       _param2 = Param2 2,-      _env1 = env1Impl+      _env1 = Extends env1Impl     } +data Env3 env = Env3 Param3 (Extends env)++instance Environment (Env3 env) where+  type Fields (Env3 env) = '[Param3]+  type Fields1 (Env3 env) = '[]+  type Super (Env3 env) = env++instance Field (Extends env) (Env3 env) where+  fieldL f (Env3 x1 x2) = fmap (\y2 -> Env3 x1 y2) (f x2)++instance Field Param3 (Env3 env) where+  fieldL f (Env3 x1 x2) = fmap (\y1 -> Env3 y1 x2) (f x1)++newtype Obj3 env = Obj3 {_runObj3 :: RIO env Int}+  deriving (Generic)++instance Interface Obj3 where+  type IBase Obj3 = RIO++obj3Impl :: Has Param1 env => Obj3 env+obj3Impl = mapBaseRIO (Env3 (Param3 3) . Extends) $+  Obj3 $ do+    Param3 n <- view getL+    Param1 m <- view getL+    pure $ n + m+ spec :: Spec spec = do   describe "getL" $ do@@ -158,3 +186,7 @@       n <- runRIO env2Impl $ do         runIF @Obj2 _method3       n `shouldBe` 3+    it "runIF @Obj3 from Env1" $ do+      n <- runRIO env1Impl $ do+        _runObj3 obj3Impl+      n `shouldBe` 4
test/Control/Env/Hierarchical/THSpec.hs view
@@ -11,6 +11,7 @@  import Control.Env.Hierarchical.Internal   ( Environment (Fields, Fields1),+    Extends,     Field (fieldL),     Root,     Super,@@ -45,12 +46,18 @@  deriveEnv ''Env -type instance Super (Env f a) = Root+newtype Param1 = Param1 Int +data Env2 = Env2 (Extends E) Param1++deriveEnv ''Env2+ spec :: Spec spec = describe "deriveEnv" $ do   it "`Super E` is Root" $ do     typeRep (Proxy @(Super E)) `shouldBe` typeRep (Proxy @Root)+  it "`Super Env2` is E" $ do+    typeRep (Proxy @(Super Env2)) `shouldBe` typeRep (Proxy @E)   it "`Fields E` is '[E, Int, Bool, Maybe E, Either Int E, F E]" $ do     typeRep (Proxy @(Fields E))       `shouldBe` typeRep (Proxy @'[E, Int, Bool, Maybe E, Either Int E, F E])
test/Control/Env/HierarchicalSpec.hs view
@@ -10,14 +10,13 @@ module Control.Env.HierarchicalSpec where  import Control.Env.Hierarchical-  ( Has,+  ( Extends (Extends),+    Has,     Has1,-    Root,     deriveEnv,     getL,     runIF,   )-import Control.Env.Hierarchical.Internal (Super) import Control.Method (Interface (IBase), mapBaseRIO) import Lens.Micro.TH (makeLenses) import RIO@@ -36,11 +35,11 @@   }  data Env2 = Env2-  { env1 :: Env1,+  { env1 :: Extends Env1,     foo :: FooObj Env2   } -data Env3 env = Env3 env Param2+data Env3 env = Env3 (Extends env) Param2  data HogeObj env = HogeObj   { _hogeMethod :: Int -> RIO env Text,@@ -67,12 +66,6 @@ deriveEnv ''Env2 deriveEnv ''Env3 -type instance Super Env1 = Root--type instance Super Env2 = Env1--type instance Super (Env3 env) = env- example1 :: (Has1 HogeObj env, Has Param1 env) => RIO env Text example1 = do   Param1 n <- view getL@@ -92,11 +85,11 @@ mkEnv2 =   Env2     { foo = mapBaseRIO mkEnv3 fooImpl,-      env1 = mkEnv1+      env1 = Extends mkEnv1     }  mkEnv3 :: env -> Env3 env-mkEnv3 env = Env3 env (Param2 5)+mkEnv3 env = Env3 (Extends env) (Param2 5)  hogeImpl :: HogeObj env hogeImpl =