【发布时间】:2017-04-27 03:30:31
【问题描述】:
在these 的第 2.3 节中,关于 DSL 的无标记最终解释器的非常酷的注释中,Oleg Kiselyov 展示了如何解决解析序列化 DSL 表达式一次的问题,并解释 em> 多次。
简而言之,他用类型证明了“假的一流多态性”
newtype Wrapped = Wrapped (∀ repr. ExpSYM repr ⇒ repr)
fromTree :: String → Either ErrMsg Wrapped
不令人满意,因为它不可扩展:对于repr 上的每个集 约束,我们必须有一个不同的Wrapper/fromTree。因此我倾向于使用他的复制器解释器解决方案。这个问题是关于如何在 HOAS 中使用该解释器。
具体来说,考虑以下语言用于目标语言绑定:
class Lam repr where
lam :: (repr a -> repr b) -> repr (a -> b)
app :: repr (a -> b) -> repr a -> repr b
我无法为我的复制器解释器提供Lam 类的声音 实例。这是我所拥有的:
data Dup repr1 repr2 a = Dup {unDupA :: repr1 a, unDupB :: repr2 a}
instance (Lam repr1, Lam repr2) => Lam (Dup repr1 repr2) where
lam f = Dup (lam $ unDupA . f . flip Dup undefined) (lam $ unDupB . f . Dup undefined)
app (Dup fa fb) (Dup a b) = Dup (app fa a) (app fb b)
有没有办法为我的Dup 类型而不涉及undefined 的东西提供Lambda 的递归 实例?
我还尝试使用来自this paper 的更强大的lam 版本,它允许monadic 解释器使用HOAS,但我不知道它对我的实例有什么帮助为Dup。使用任何一个版本的 lam 和 HOAS 的解决方案都会很棒!
*:Oleg 展示了如何使用 de Bruijn 索引定义声音实例,但我对 HOAS 的解决方案非常感兴趣。
class Lam repr where
lam :: repr (a,g) b -> repr g (a -> b)
app :: repr g (a->b) -> repr g a -> repr g b
data Dup repr1 repr2 g a = Dup{d1:: repr1 g a, d2:: repr2 g a}
instance (Lam repr1, Lam repr2) => Lam (Dup repr1 repr2) where
lam (Dup e1 e2) = Dup (lam e1) (lam e2)
app (Dup f1 f2) (Dup x1 x2) = Dup (app f1 x1) (app f2 x2)
【问题讨论】:
-
这似乎不太可能。你不能从
(r1, r2) -> (r1, r2)到(r1 -> r1, r2 -> r2),这需要使用(Lam r1, Lam r2)来实现Lam (Dup r1 r2)。 -
@Li-yaoXia 我也想过从
(a -> m b) -> m (a -> b)到任意Monad m,直到我阅读了第二篇链接的论文。我正在等待另一个类似的惊人解决方案。 -
@crockeea 是一个可以在论文上下文之外描述的“技巧”,或者我可以跳转到某个页面以快速了解它是如何工作的吗?跨度>
-
“不纯但卫生代码的组合器”的第 3 节有一个很好的描述,特别是第 28 页,他们切中要害。
-
一种解决方案是从 HOAS 切换到 PHOAS,但我不知道对于您需要此代码的任何其他目的,这是否会使您的生活更轻松或更困难。但是这个改变将修复赏金评论中的三点。更改非常简单——将
lam的类型更改为(v a -> repr v b) -> repr v (a -> b);对于不绑定变量的类型,repr变为repr v;你需要var :: v a -> repr v a。