我正在编写一个项目,涉及组成多个堆栈StateT和ReaderT单子:
newtype FooT m a = FooT { unFooT :: (StateT State1 (ReaderT Reader1 m)) a }
newtype BarT m a = BarT { unBarT :: (StateT State2 (ReaderT Reader2 m)) a }
Run Code Online (Sandbox Code Playgroud)
然后,我基本上只是运行所有内容FooT (BarT m)并根据需要提升到适当的 monad。我用来lens与各种状态/阅读器类型进行交互:
foo :: Monad m => FooT m ()
foo = do
field1 .= ... -- where field1 is a lens into State1
...
Run Code Online (Sandbox Code Playgroud)
然而,当我添加更多StateT+ReaderT变压器时,这种方法变得丑陋(并且似乎可能会产生一些性能成本)。
到目前为止,我唯一的想法是将以下状态结合起来:
newtype BazT m a = BazT …Run Code Online (Sandbox Code Playgroud) 我正在使用该benchpress库运行一些相当简单的基准测试。我一直在使用bench :: Int -> IO a -> IO ()界面。但是,似乎如果我运行给定的函数n次数,第一个之后的所有运行都非常快。
作为一个简单的例子,bench 1 (seq (sum [1..100000]) (return ()))可能需要 10 秒左右。但是,bench 5 (seq (sum [1..100000]) (return ()))会产生这样的报告:
Times (ms)
min mean +/-sd median max
0.001 2.657 5.937 0.001 13.277
Percentiles (ms)
50% 0.001
66% 0.002
75% 0.002
80% 0.002
90% 13.277
95% 13.277
98% 13.277
99% 13.277
100% 13.277
Run Code Online (Sandbox Code Playgroud)
由于平均值是 2.6,我可以推断出第一次运行需要 13 秒,其他 4 秒非常快。
为什么会发生这种情况?如何确保基准测试的所有运行都具有代表性?该库还具有更细粒度的界面:benchmark :: Int -> IO a -> …
我想编写一种可以通过其 monad 转换器参数化的类型。我尝试了几件事,最终得到了一些类似的东西:
newtype Foo t a = Foo { unFoo :: t (State St) a }
Run Code Online (Sandbox Code Playgroud)
然后,我想要一堆实例:
deriving instance (MonadTrans t, Monad (t (State St))) => Monad (Foo t)
Run Code Online (Sandbox Code Playgroud)
最后,我使用适当的 monad 转换器实例化类型。我的代码类型检查,但我收到所有派生实例的警告:“没有明确的实现>>=”。如果我尝试运行它,当它遇到类型类函数时会出现未定义的错误。
有没有办法自动派生我需要的所有实例?我试图派生出更多的类,而不仅仅是Monad.
我也对一种更符合人体工程学的方式来完成同样的事情感兴趣——我必须不断手动包装和解开Foo构造函数,特别是当我尝试对其lift进行计算时,因为我无法弄清楚如何实现一个MonadTrans实例为了它。
是否有组合器可以以 pointfree 风格编写 Haskell 类型?
我有一个类似的类型同义词:
type FooT m a = StateT State (ReaderT (Params m) m)
Run Code Online (Sandbox Code Playgroud)
我希望能够以 pointfree 风格编写它的右侧,以便实例化一个需要参数为 monad 转换器的类型类。即,有一些类型类,例如:
class (MonadTrans t, Bar (t Monad)) => Baz t where -- where Bar is some other typeclass
...
Run Code Online (Sandbox Code Playgroud)
我想用我的变压器堆栈实例化它。但是,我需要向它提供某种类型的东西(* -> *) -> * -> *,这意味着我需要编写一个类型级函数,以便将我的StateT State (ReaderT ...)转换器作为参数传递给类型类。
我尝试使用类型系列,但似乎它们需要完全应用。