- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我基于 ReaderT design pattern 构建了一个项目.我没有使用类型类方法进行依赖注入(inject),而是选择使用简单的处理程序注入(inject)作为函数参数。这部分工作正常,因为能够静态构建依赖树并动态定义环境。
环境可能包含配置以及日志效果 ::String -> IO ()
,时间效果 ::IO UTCDate
等。考虑以下内容缩小的例子
import Control.Monad.Reader (runReaderT, liftIO, reader, MonadReader, MonadIO)
data SomeEnv
= SomeEnv
{ a :: Int
, logger :: String -> IO ()
}
class HasLogger a where
getLogger :: a -> (String -> IO())
instance HasLogger SomeEnv where
getLogger = logger
myFun :: (MonadIO m, MonadReader e m, HasLogger e) => Int -> m Int
myFun x = do
logger <- reader getLogger
liftIO $ logger "I'm going to multiply a number by itself!"
return $ x * x
doIt :: IO Int
doIt = runReaderT (myFun 1337) (SomeEnv 13 putStrLn)
是否可以概括记录器的效果?
logger :: String -> m ()
出于使用适合 monad 堆栈的记录器的动机
myFun x = do
logger <- reader getLogger
logger "I'm going to multiply a number by itself!"
return $ x * x
最佳答案
我们可以尝试以下更改:
HasLogger
成为一个双参数类型类,将环境与“基础”monad 相关联。像这样:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneKindSignatures #-}
import Control.Monad.IO.Class
import Control.Monad.Reader
import Data.Kind (Constraint, Type)
type RT m = ReaderT (SomeEnv m) m
type SomeEnv :: (Type -> Type) -> Type
data SomeEnv m = SomeEnv
{ a :: Int,
logger :: String -> RT m (),
-- I'm putting the main fuction in the record,
-- perhaps we'll want to inject it into other logic, later.
myFun :: Int -> RT m Int
}
type HasLogger :: Type -> (Type -> Type) -> Constraint
class HasLogger r m | r -> m where
getLogger :: r -> String -> m ()
instance HasLogger (SomeEnv m) (RT m) where
getLogger = logger
_myFun :: (MonadReader e m, HasLogger e m) => Int -> m Int
_myFun x = do
logger <- reader getLogger
logger "I'm going to multiply a number by itself!"
return $ x * x
现在 _myFun
没有 MonadIO
约束。
我们可以创建一个示例环境并运行 myFun
:
env =
SomeEnv
{ a = 13,
logger = liftIO . putStrLn,
myFun = _myFun
}
doIt :: IO Int
doIt = runReaderT (myFun env 1337) env
此解决方案的一个缺点是环境中的函数签名变得更加复杂,即使使用 RT
类型同义词也是如此。
编辑:为了简化环境中的签名,我尝试了这些替代定义:
type SomeEnv :: (Type -> Type) -> Type
data SomeEnv m = SomeEnv
{ a :: Int,
logger :: String -> m (), -- no more annoying ReaderT here.
myFun :: Int -> m Int
}
instance HasLogger (SomeEnv m) m where
getLogger = logger
-- Yeah, scary. This newtype seems necessary to avoid an "infinite type" error.
-- Only needs to be defined once. Could we avoid it completely?
type DepT :: ((Type -> Type) -> Type) -> (Type -> Type) -> Type -> Type
newtype DepT env m r = DepT { runDepT :: ReaderT (env (DepT env m)) m r }
deriving (Functor,Applicative,Monad,MonadIO,MonadReader (env (DepT env m)))
instance MonadTrans (DepT env) where
lift = DepT . lift
env' :: SomeEnv (DepT SomeEnv IO) -- only the signature changes here
env' =
SomeEnv
{ a = 13,
logger = liftIO . putStrLn,
myFun = _myFun
}
doIt :: IO Int
doIt = runReaderT (runDepT (myFun env' 1337)) env'
DepT
基本上是一个 ReaderT
,但是我们知道它的环境是由 DeptT
本身参数化的。它具有通常的实例。
_myFun
不需要更改此替代定义。
关于haskell - ReaderT 设计模式 : Parametrize the Environment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61780295/
我想在 32 位 Windows 上获取路径 system32 路径,在 64 位 Windows 上获取路径 SysWOW64。 Environment.GetFolderPath(Environm
我可以在 environment.yml 中设置环境变量吗? conda 中的文件环境? conda 让我 save environment variables in environments通过 e
我一直在尝试大部分 Enviroment.SpecialFolder 枚举,但我认为没有任何方法可以通过枚举。使用 string.Substring() 方法给我带来了最大的收获。 我尝试只获取实际安
当我在 .ios 项目的 appDelegate 中使用 Environment.GetFolderPath(Environment.SpecialFolder.Personal) 时,我得到一个路径
我找到了 this project在做一些研究的同时。我注意到 Docker Compose 示例文件中的这一行: environment: &environment 所以我想知道它实际上意味着什么?
在 python/flask/gunicorn/heroku 堆栈上,我需要根据另一个 env 变量的内容设置一个环境变量。 作为背景,我在 heroku 上运行了一个 python/Flask 应用
我正在尝试使用 angularfire @angular/[email protected] 构建 Angular 15 。但我遇到了这个错误 ✔ Downloading configuration
我在我的一位客户的计算机上遇到了一个非常奇怪的行为,我找不到任何线索来解释为什么会这样:当应用程序调用 Environment.GetFolderPath(Environment.SpecialFol
我遇到了以下方法: Environment.getDataDirectory() : /data 和 getFilesDir() : /data/data/package/files 一种方法使用环境
我在 rails 中有一个迁移,它执行以下操作: class AddMissingIndexes :evid, :length => { :evid => 255 } end end 但是,在对
所以我对 MS Stack Development 世界相当陌生,面临着本地开发环境与服务器环境不同的问题(我认为它们是一样的,但我错了)。 我的设置是使用 Visual Studio 2012(II
我有一个只包含 exe 文件(没有源代码)的 hello 工具。 你好工具结构: bin helloBin.exe helloRoot.exe conanfile.py conanfile.py
我是 R 的新用户,我尝试了以下代码。它给出了一个错误。任何人都可以帮忙吗?代码是: library(ggplot2) data(diamonds) qplot(price, data=diamond
我正在使用以下方法获取 Windows 7 中“我的文档”文件夹的路径并遍历其目录: Dim diri As New DirectoryInfo(Environment.GetFolderPath(E
我试图通过更改其环境变量来修改 Linux 上 JetBrains Rider 中 .NET 项目的设置配置文件。但是,当我点击文件夹图标时,我无法点击添加、删除或修改任何环境变量。 我注意到在 Ri
这个问题已经有答案了: How to add package to conda environment without pip (5 个回答) 已关闭 1 年前。 我在没有连接到互联网的计算机上安装了
我开发了一个 Controller 来使用 JSON 响应 AJAX 请求: class PeopleController extends Controller { public function l
我有一个 asp.net mvc3 应用程序。现在我想将用户数据保存在 C:\Users{AppPoolUserAccount}\AppData\Roaming\MyProgramm... 在第一次调
#include #include #include extern char *environ[]; int main(int argc, char *argv[]) { int ind
我在将 json 文件导入 typescript 时遇到问题。我已经按照惯例配置了tsconfig.json,但是在environment.ts文件中还是不行,但是在environment.prod.
我是一名优秀的程序员,十分优秀!