拷贝机解释与高阶像差
在these对DSL的无标签的最终解释很酷的注释部分2.3,奥列格Kiselyov展示了如何解决解析问题的一个序列化的DSL表达式一次,解释它多次。拷贝机解释与高阶像差
简单地说,他表示“假一流多态性”的同类型
newtype Wrapped = Wrapped (∀ repr. ExpSYM repr ⇒ repr)
fromTree :: String → Either ErrMsg Wrapped
并不令人满意,因为它是不可扩展的:我们必须对每设置的不同Wrapper
/fromTree
限制repr
。因此,我倾向于使用他的解决方案复制解释器。这个问题是关于如何在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)
是否有某种方式来给出一个Lambda
递归例如的东西,像我Dup
型,不涉及undefined
?
我也利用this paper,允许单子口译与人道主义组织和机构的lam
的更强大的版本,但我没有看到它如何帮助我的实例Dup
尝试。使用HOAS版本lam
的解决方案将会非常棒!
*:奥列格展示了如何使用定义德布鲁因指数健全的情况下,但我在高阶像差的解决方案很感兴趣。
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)
这是不可能的。
要显示一个例子,我首先做的Lam
一个很简单的例子:
newtype Id a = Id a
instance Lam Id where
lam (Id f) = Id (\x -> let Id r = f x in r)
app (Id f) (Id x) = Id (f x)
现在,我会让那对Dup
小号进行动作的功能:
f :: Dup Id Id Int -> Dup Id Id Int
f (Dup (Id x) (Id y)) = Dup (Id x*y) (Id y)
我会,从Lam
实例中,能够做到lam f :: Dup Id Id (Int -> Int)
。 这可能看起来像
Dup (Id (\x -> x*y)) (Id (\y -> y))
它不能进行,因为y
是不能从x
-Lambda。 (使用undefined
代替y
这里undefined
,抛出运行时错误,只要它不能很好地工作。) 这不是一件很少见的事情:任何时候在其他结果中使用其中一个变量时都会发生这种情况。
我不知道你与Monad
-generalized一个更强的要求相当的,但这种情况与其他Monad
S,太:例如,与Maybe
,你不能把以下为Maybe (Int -> Int)
,因为这取决于给定的值:
f :: Maybe Int -> Maybe Int
f m = m >>= \x -> if x > 5 then Just x else Nothing
(你可以用它fromJust
和希望没有人这样做,但它是一样的undefined
的解决方案。)只有
的undefined
之遥,如果一个错误该功能需要t然而,看看其他变量。如果您完全确定它永远不会运行在这样的任何事情上(例如,您将展开/创建限制到经过广泛测试的隐藏模块),那么undefined
的方式将起作用。
只是多一个建议:使用更详细的error
消息而不是undefined
,以防出错出错。
在模板Haskell做了一些工作后,我有一个适用于这里的想法。另一种选择是做TH的方式做:
class Fail.MonadFail m => Quasi m where
-- All the things here, like inspecting types, generating names, etc.
...
-- Many instances, including
instance Quasi IO where ... -- So you can debug your TH
instance TH.Quasi GHCiQ where ... -- see https://github.com/ghc/ghc/blob/master/libraries/ghci/GHCi/TH.hs#L167
instance TH.Quasi TcM where ... -- see https://github.com/ghc/ghc/blob/master/compiler/typecheck/TcSplice.hs#L835
data Q a = { unQ :: forall m. Quasi m => m a }
instance Quasi Q where ...
您可以找到Q
单子的定义here。
的端用户工作的Q
单子内,并且它可以由任何内部编译器解释器,或IO
单子进行调试等。任何复制由forall
处理进行解释。你可以,同样,这样做
data L a = { unL :: forall repr. Lam repr => repr a }
instance Lam L where ...
myEndUserThing :: L ((a -> b) -> a -> b)
myEndUserThing = lam $ \f -> lam $ \x -> app f x
很容易转换到你需要的任何其他repr
,如果你需要更多的功能,只需将其添加到Lam
类或创建一个额外功能的派生类。
这似乎不太可能。你不能从'(r1,r2) - >(r1,r2)'到'(r1 - > r1,r2 - > r2)'获得,这将需要实现'Lam(Dup r1 r2)' '(Lam r1,Lam r2)'。 –
@ Li-yaoXia对于任意一个“Monad m”,我认为从一个'(a - > m b) - > m(a - > b)'是一样的,直到我读到第二个链接的纸。我支持另一个类似的惊人的解决方案。 – crockeea
@crockeea是一种可以在论文的上下文之外描述的“诀窍”,或者我可以跳到某个页面以便快速了解该如何工作? – jberryman