用 Haskell 解释 Parigot 的 lambda-mu 演算

2024-02-21

我们可以用 Haskell 来解释 lambda 演算:

data Expr = Var String | Lam String Expr | App Expr Expr

data Value a = V a | F (Value a -> Value a)

interpret :: [(String, Value a)] -> Expr -> Value a
interpret env (Var x) = case lookup x env of
  Nothing -> error "undefined variable"
  Just v -> v
interpret env (Lam x e) = F (\v -> interpret ((x, v):env) e)
interpret env (App e1 e2) = case interpret env e1 of
  V _ -> error "not a function"
  F f -> f (interpret env e2)

上述解释器如何扩展到lambda-mu演算 http://en.wikipedia.org/wiki/Lambda-mu_calculus?我的猜测是,它应该使用延续来解释该演算中的附加结构。 (15) 和 (16) 从是我所期望的翻译。

这是可能的,因为 Haskell 是图灵完备的,但如何实现呢?

Hint:请参阅第 197 页上的评论这篇研究论文 http://www.cs.ru.nl/~freek/courses/tt-2011/papers/parigot.pdfmu 绑定器的直观含义。


这是论文中归约规则的无意识音译,使用@user2407038的表示(正如你所看到的,当我说无意识时,我确实是指无意识):

{-# LANGUAGE DataKinds, KindSignatures, GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}

import Control.Monad.Writer
import Control.Applicative
import Data.Monoid

data TermType = Named | Unnamed

type Var = String
type MuVar = String

data Expr (n :: TermType) where
  Var :: Var -> Expr Unnamed
  Lam :: Var -> Expr Unnamed -> Expr Unnamed
  App :: Expr Unnamed -> Expr Unnamed -> Expr Unnamed
  Freeze :: MuVar -> Expr Unnamed -> Expr Named
  Mu :: MuVar -> Expr Named -> Expr Unnamed
deriving instance Show (Expr n)

substU :: Var -> Expr Unnamed -> Expr n -> Expr n
substU x e = go
  where
    go :: Expr n -> Expr n
    go (Var y) = if y == x then e else Var y
    go (Lam y e) = Lam y $ if y == x then e else go e
    go (App f e) = App (go f) (go e)
    go (Freeze alpha e) = Freeze alpha (go e)
    go (Mu alpha u) = Mu alpha (go u)

renameN :: MuVar -> MuVar -> Expr n -> Expr n
renameN beta alpha = go
  where
    go :: Expr n -> Expr n
    go (Var x) = Var x
    go (Lam x e) = Lam x (go e)
    go (App f e) = App (go f) (go e)
    go (Freeze gamma e) = Freeze (if gamma == beta then alpha else gamma) (go e)
    go (Mu gamma u) = Mu gamma $ if gamma == beta then u else go u

appN :: MuVar -> Expr Unnamed -> Expr n -> Expr n
appN beta v = go
  where
    go :: Expr n -> Expr n
    go (Var x) = Var x
    go (Lam x e) = Lam x (go e)
    go (App f e) = App (go f) (go e)
    go (Freeze alpha w) = Freeze alpha $ if alpha == beta then App (go w) v else go w
    go (Mu alpha u) = Mu alpha $ if alpha /= beta then go u else u

reduceTo :: a -> Writer Any a
reduceTo x = tell (Any True) >> return x

reduce0 :: Expr n -> Writer Any (Expr n)
reduce0 (App (Lam x u) v) = reduceTo $ substU x v u
reduce0 (App (Mu beta u) v) = reduceTo $ Mu beta $ appN beta v u
reduce0 (Freeze alpha (Mu beta u)) = reduceTo $ renameN beta alpha u
reduce0 e = return e

reduce1 :: Expr n -> Writer Any (Expr n)
reduce1 (Var x) = return $ Var x
reduce1 (Lam x e) = reduce0 =<< (Lam x <$> reduce1 e)
reduce1 (App f e) = reduce0 =<< (App <$> reduce1 f <*> reduce1 e)
reduce1 (Freeze alpha e) = reduce0 =<< (Freeze alpha <$> reduce1 e)
reduce1 (Mu alpha u) = reduce0 =<< (Mu alpha <$> reduce1 u)

reduce :: Expr n -> Expr n
reduce e = case runWriter (reduce1 e) of
    (e', Any changed) -> if changed then reduce e' else e

它对于论文中的示例“有效”:

example 0 = App (App t (Var "x")) (Var "y")
  where
    t = Lam "x" $ Lam "y" $ Mu "delta" $ Freeze "phi" $ App (Var "x") (Var "y")   
example n = App (example (n-1)) (Var ("z_" ++ show n))

我可以减少example n达到预期结果:

*Main> reduce (example 10)
Mu "delta" (Freeze "phi" (App (Var "x") (Var "y")))

我在上面的“works”周围加上引号的原因是我对 λμ 演算没有直觉,所以我不知道它应该做什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 Haskell 解释 Parigot 的 lambda-mu 演算 的相关文章

  • 如何在 Simple Build Tool 项目中调用 scala 解释器?

    我的 scala 程序正在使用 scala tools nsc interpreter IMain 的编译器接口 当我用 scalac 编译时 一切都按预期进行 但是当我使用 sbt 编译时 它仍然可以编译 但在执行时 它会在从 IMain
  • 机器和管道(或其他类似的库)之间的概念区别是什么?

    我想学习这个概念 以便我能够理解和使用诸如machines http hackage haskell org package machines 我试着跟随R nar Bjarnason 关于机器的演讲 https dl dropbox co
  • 如何在 Windows 7 中配置 cabal?

    我已经在Windows 7中安装了Haskell Platform 2012 我在控制台中编写cabal update我收到消息说有新版本的阴谋集团 我写的cabal install cabal install 安装完成后 它告诉我 cab
  • 我需要什么类型签名才能将函数列表转换为 Haskell 代码? [复制]

    这个问题在这里已经有答案了 可能的重复 为什么 haskell 中不允许这样的函数定义 https stackoverflow com questions 6168880 why is such a function definition
  • 在 Haskell 中提升 State monad 中的值

    我正在 Haskell 中编写一个数独生成器 求解器作为学习练习 My solve函数接受一个UArray但返回一个State Int UArray 这样它也可以返回解决问题时发现的最大难度级别 到目前为止 这是我的功能 仍处于实验性的早期
  • 在 Haskell 中阅读 GraphML

    我正在尝试将包含单个有向图的 GraphML 文件读入 HaskellData Graph http hackage haskell org package containers 0 2 0 1 docs Data Graph html为了
  • 让 GHC 生成“带进位加法 (ADC)”指令

    下面的代码将表示 192 位数字的两个未装箱字三元组添加到新的未装箱字三元组中 并且还返回任何溢出 LANGUAGE MagicHash LANGUAGE UnboxedTuples import GHC Prim plusWord2 Wo
  • 如何在 Haskell 中获得列表的中间位置?

    我刚刚开始使用 Haskel 学习函数式编程 我正在慢慢度过Erik Meijer 在 Channel 9 的讲座 http channel9 msdn com shows Going Deep Lecture Series Erik Me
  • 显示未定义的实例

    可以采取任何措施来为未定义的值定义 Show 实例吗 也许存在一些 GHC 扩展 我想要这样的东西 gt print 1 undefined 1 undefined 根据Haskell 2010 报告 第 9 章 http www hask
  • 在 Haskell 中将字节转换为 Int64s/Floats/Doubles

    我正在尝试解析 Haskell 中的二进制文件格式 Apple 的二进制属性列表格式 该格式所需的内容之一是将字节序列视为 a 无符号 1 2 或 4 字节整数 b 有符号 8 字节整数 c 32 位floats d 64 位doubles
  • Haskell 中函数和函子有什么区别?只有定义吗?

    在 Haskell 中 当编写函数时 这意味着我们将某个东西 输入 映射到另一个东西 输出 我尝试 LYAH 来理解 Functor 的定义 看起来和普通 Functor 一样 函数被称为函子有什么限制吗 Functor 是否允许有 I O
  • 访问函数中的环境

    In main我可以读取我的配置文件 并将其提供为runReader somefunc myEnv正好 但somefunc不需要访问myEnv读者提供 链中的下一对也没有提供 需要 myEnv 中某些内容的函数是一个微小的叶函数 如何在不将
  • Haskell 类型系统的细微差别

    我一直在深入了解 haskell 类型系统的本质 并试图了解类型类的要点 我已经学到了很多东西 但我在下面的代码片段上遇到了困难 使用这些类和实例定义 class Show a gt C a where f Int gt a instanc
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 持久 selectList 导致错误“无法将类型‘BaseBackend backend0’与‘SqlBackend’匹配”

    我遇到以下编译错误 Couldn t match type BaseBackend backend0 with SqlBackend arising from a use of runSqlite The type variable bac
  • 搜索重写规则

    有什么办法可以浏览或搜索重写规则吗 当我使用像这样的标志时 ddump rule firings or ddump rule rewrites我只是得到了触发的规则的名称以及它引起的重写 但没有得到实际的规则本身 理想情况下 我想通过 GH
  • 规范化且不可变的数据模型

    Haskell如何解决 规范化不可变数据结构 问题 例如 让我们考虑一个表示前女友 男友的数据结构 data Man Man name String exes Woman data Woman Woman name String exes
  • Haskell 泛化问题(涉及列表理解)

    假设我想知道a上的所有要点 x y 矩形内的平面has 我可以使用列表推导式来计算 如下所示 let myFun2D x y x lt 0 2 y lt 0 2 现在 如果我想为一个人完成同样的事情 x y z 空间 我可以采取同样的方式并
  • 使用 FoldLine 解析多个块

    对于这个简化的问题 我试图解析一个如下所示的输入 foo bar baz quux woo hoo xyzzy glulx into foo bar baz quux woo hoo xyzzy glulx 我尝试过的代码如下 import
  • 如何在 Haskell 中制作打勾游戏的图案?

    实现有 2 个参数的函数 ticktick 第一个参数是自然数元组 定义游戏场地的行数和列数 第二个列表包含由玩家 x 和玩家 o 轮流玩的坐标给出的井字游戏比赛的记录 打印游戏的实际状态 其中游戏区域将由字符 和 界定 空方块 以及字符

随机推荐