可以为FreeT/ProgramT创建的monad变换器提供类似mtl的机制吗?
我对历史的理解如下.曾几何时,monad变压器被发明了.然后人们开始在另一个上堆叠monad变换器,然后发现插入lift到处都很烦人.然后有几个人发明了monad类,所以我们可以ask :: m r在任何monad中m这样做MonadReader r m.这可以通过让每个monad类穿透每个monad变换器来实现
(Monoid w, MonadState s m) => MonadState s (WriterT w m)
MonadWriter w m => MonadWriter w (StateT s m)
你需要为每对monad变换器提供这样的实例声明对,所以当有n个 monad变换器时,你需要n ^ 2个成本.然而,这不是一个大问题,因为人们将主要使用预定义的monad并且很少创建自己的monad.到目前为止,我理解这个故事,并且在下面的问答中也详细说明:
然后我的问题是新的免费monad http://hackage.haskell.org/package/free和操作monads http://hackage.haskell.org/package/operational.它们允许我们编写自己的DSL并将其用作monad,只需将语言定义为某种代数data类型(Operational甚至不需要Functor实例).好消息是我们可以免费获得monad和monad变换器; 那么monad课怎么样?坏消息是"我们很少定义我们自己的monad变换器"的假设不再成立.
为了解这个问题,我做了两个ProgramT,让它们相互渗透;
https://github.com/nushio3/practice/blob/master/operational/exe-src/test-05.hs
该operational包不支持monad类,所以我采用了另一个实现minioperational并将其修改为我需要的工作; https://github.com/nushio3/minioperational
不过,我需要专门的实例声明
instance (Monad m, Operational ILang m) => Operational ILang (ProgramT SLang m) where
因为以下形式的一般声明会导致不可判定的实例.
instance …
这是库里 - 霍华德的双重否定的记者a; (a -> r) -> r或者(a -> ?) -> ?,或两者兼而有之?
两种类型都可以在Haskell中编码如下,其中?编码为forall b. b.
p1 :: forall r. ((a -> r) -> r)
p2 :: (a -> (forall b. b)) -> (forall b. b)
Run Code Online (Sandbox Code Playgroud)
Wadler 2003的论文以及 Haskell中的实现似乎采用了前者,而其他一些文献(例如本文)似乎支持后者.
我目前的理解是后者是正确的.我理解前者的风格,因为你可以创建类型的值的困难a,从forall r. ((a -> r) -> r)使用纯计算:
> let p1 = ($42) :: forall r. (Int -> r) -> r
> p1 id
42
Run Code Online (Sandbox Code Playgroud)
这似乎与你不能获得直觉逻辑相矛盾 …
透镜,记录访问器如何,例如
http://hackage.haskell.org/packages/archive/lens/3.9.0.2/doc/html/Control-Lens-Type.html#t:Lens
与变形相关?例如
你能说前者是后者的一个例子吗?
我最近一直在使用镜头.在Haskell编程中,镜头在许多方面都至关重要; 它们是记录访问,有状态程序的工具......为了更好地理解镜头,我开始阅读"香蕉,镜片,信封和铁丝网"纸.在"INSIDE 206-105"的帮助下,我慢慢地重新实现了Haskell中的-morphisms.然后上面的问题发生在我身上.
最近,我学习了如何实现具有反引号功能的准引号,如printfQ下面的代码所示:
main = do
let itemName = "apple"
price = 1.29
[printfQ| The price of #{itemName} is #{price}. |]
Run Code Online (Sandbox Code Playgroud)
准引号的成分字符串将被传递到quoteExp printfQ :: String -> ExpQ. 所以我们要做的就是解析给定的String,找到要嵌入的名称"itemName","price"应用varE . mkName每个名称,并构建ExpQ.
现在假设我想扩展它printfQ以允许表达式嵌入,如下所示:
[printfQ| The price of #{itemNames !! i} is #{price + taxOf price}. |]
"itemNames !! i"我可以编写检测两个字符串和 的解析器"price + taxOf price"。但随后我需要一个更强版本的,这是一个将这些字符串转换为varE . mkName的函数,将它们解释为引用所使用的命名空间的表达式。String -> ExpQExpQprintfQ
我的问题:是否有任何库函数可以将此字符串转换为 AST?有一些简单的方法可以做到这一点,还是我需要编写整个 …
haskell ×4
curry-howard ×1
free-monad ×1
haskell-lens ×1
operational ×1
quotations ×1
recursion ×1