在 Haskell 中简单输入 lambda 演算失败

2023-11-23

我是 Haskell 的新手,所以如果这个问题没有太大意义,我深表歉意。

我希望能够在 Haskell 中实现简单类型的 lambda 表达式,这样当我尝试将一个表达式应用于另一个表达式时wrongtype,结果不是类型错误,而是一些设置值,例如没有什么。起初我认为使用 Maybe monad 将是正确的方法,但我无法让任何东西发挥作用。我想知道如果有的话,正确的方法是什么。

如果有帮助的话,问题的背景是我正在从事的一个项目,该项目为句子中的单词分配 POS(词性)标签。对于我的标签集,我使用分类语法类型;这些是类型化的 lambda 表达式,例如(e -> s) or (e -> (e -> s)), where e and s分别是名词和句子的类型。例如,kill有类型(e -> (e -> s))- 它需要两个名词短语并返回一个句子。我想要编写一个函数,该函数接受此类类型的对象列表,并找出是否有任何方法将它们组合起来以达到该类型的对象s。当然,这正是 Haskell 的类型检查器所做的事情,因此为每个单词分配适当类型的 lambda 表达式应该很简单,然后让 Haskell 完成其余的工作。问题是,如果s无法到达,Haskell 的类型检查器自然会停止程序运行。


我想用一种稍微不同的方法来扩展 @Daniel Wagner 的优秀答案:不是返回有效类型(如果有的话)的类型检查,而是返回一个类型化表达式,然后保证我们可以对其进行求值(因为简单类型的 lambda微积分是强标准化的)。基本思想是check ctx t e回报Just (ctx |- e :: t) iff e可以输入t在某些情况下ctx,然后给出一些键入的表达式ctx |- e :: t,我们可以用一些方法来评价它Env正确类型的熨烫。

实施情况

我将使用单例来模拟 Pi 类型check :: (ctx :: [Type]) -> (a :: Type) -> Term -> Maybe (TTerm ctx a),这意味着我们需要打开每个 GHC 扩展和厨房水槽:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds, KindSignatures, TypeFamilies, TypeOperators #-}
{-# LANGUAGE TemplateHaskell #-} -- sigh...

import Data.Singletons.Prelude
import Data.Singletons.TH
import Data.Type.Equality

第一个位是非类型化表示,直接来自 @Daniel Wagner 的回答:

data Type = Base
          | Arrow Type Type
          deriving (Show, Eq)

data Term = Const
          | Var Int
          | Lam Type Term
          | App Term Term
          deriving Show

但我们还将通过解释来给出这些类型的语义Base as () and Arrow t1 t2 as t1 -> t2:

 type family Interp (t :: Type) where
    Interp Base = ()
    Interp (Arrow t1 t2) = Interp t1 -> Interp t2

为了与 de Bruijn 主题保持一致,上下文是类型列表,变量是上下文的索引。给定上下文类型的环境,我们可以查找变量索引来获取值。注意lookupVar是一个总函数。

data VarIdx (ts :: [Type]) (a :: Type) where
    Here :: VarIdx (a ': ts) a
    There :: VarIdx ts a -> VarIdx (b ': ts) a

data Env (ts :: [Type]) where
    Nil :: Env '[]
    Cons :: Interp a -> Env ts -> Env (a ': ts)

lookupVar :: VarIdx ts a -> Env ts -> Interp a
lookupVar Here      (Cons x _)  = x
lookupVar (There v) (Cons _ xs) = lookupVar v xs

好的,我们已经准备好所有基础设施来实际编写一些代码。首先,让我们定义一个类型表示Term,与(总计!)评估器一起:

data TTerm (ctx :: [Type]) (a :: Type) where
    TConst :: TTerm ctx Base
    TVar :: VarIdx ctx a -> TTerm ctx a
    TLam :: TTerm (a ': ctx) b -> TTerm ctx (Arrow a b)
    TApp :: TTerm ctx (Arrow a b) -> TTerm ctx a -> TTerm ctx b

eval :: Env ctx -> TTerm ctx a -> Interp a
eval env TConst = ()
eval env (TVar v) = lookupVar v env
eval env (TLam lam) = \x -> eval (Cons x env) lam
eval env (TApp f e) = eval env f $ eval env e

到目前为止,一切都很好。eval是很好的和总的,因为它的输入只能表示简单类型 lambda 演算的类型良好的项。因此,@Daniel 评估器的部分工作必须将非类型化表示转换为类型化表示。

背后的基本思想infer如果类型推断成功,则返回Just $ TheTerm t e, where t is a Sing莱顿见证者e's type.

$(genSingletons [''Type])
$(singDecideInstance ''Type)

-- I wish I had sigma types...
data SomeTerm (ctx :: [Type]) where
    TheTerm :: Sing a -> TTerm ctx a -> SomeTerm ctx

data SomeVar (ctx :: [Type]) where
    TheVar :: Sing a -> VarIdx ctx a -> SomeVar ctx

-- ... and pi ones as well
infer :: Sing ctx -> Term -> Maybe (SomeTerm ctx)
infer _ Const = return $ TheTerm SBase TConst
infer ts (Var n) = do
    TheVar t v <- inferVar ts n
    return $ TheTerm t $ TVar v
infer ts (App f e) = do
    TheTerm t0 e' <- infer ts e
    TheTerm (SArrow t0' t) f' <- infer ts f
    Refl <- testEquality t0' t0
    return $ TheTerm t $ TApp f' e'
infer ts (Lam ty e) = case toSing ty of
    SomeSing t0 -> do
        TheTerm t e' <- infer (SCons t0 ts) e
        return $ TheTerm (SArrow t0 t) $ TLam e'

inferVar :: Sing ctx -> Int -> Maybe (SomeVar ctx)
inferVar (SCons t _) 0 = return $ TheVar t Here
inferVar (SCons _ ts) n = do
    TheVar t v <- inferVar ts (n-1)
    return $ TheVar t $ There v
inferVar _ _ = Nothing

希望最后一步是显而易见的:因为我们只能评估给定类型的类型良好的术语(因为这就是给我们其 Haskell 嵌入的类型),所以我们将类型infer进入类型checking:

check :: Sing ctx -> Sing a -> Term -> Maybe (TTerm ctx a)
check ctx t e = do
    TheTerm t' e' <- infer ctx e
    Refl <- testEquality t t'
    return e'

示例会话

让我们在 GHCi 中尝试一下我们的函数:

λ» :set -XStandaloneDeriving -XGADTs
λ» deriving instance Show (VarIdx ctx a)
λ» deriving instance Show (TTerm ctx a)

λ» let id = Lam Base (Var 0) -- \x -> x
λ» check SNil (SBase `SArrow` SBase) id
Just (TLam (TVar Here))

λ» let const = Lam Base $ Lam Base $ Var 1 -- \x y -> x
λ» check SNil (SBase `SArrow` SBase) const
Nothing -- Oops, wrong type
λ» check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
Just (TLam (TLam (TVar Here)))

λ» :t eval Nil <$> check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
eval Nil <$> check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
  :: Maybe (() -> () -> ())
-- Note that the `Maybe` there comes from `check`, not `eval`!
λ» let Just const' = check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
λ» :t eval Nil const'
eval Nil const' :: () -> () -> ()
λ» eval Nil const' () ()
()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Haskell 中简单输入 lambda 演算失败 的相关文章

  • 在 lambda 中延迟初始化和缓存内部值的简洁方法

    首先用简单的方法让代码自己说话 int heavy calc needed to be called once sleep 7500000 years return 42 int main auto foo And cached for l
  • 以下两个 lambda 函数的空间复杂度

    我正在阅读以下内容 https en wikibooks org wiki Haskell Graph reduction https en wikibooks org wiki Haskell Graph reduction 其内容如下
  • 嵌套字段的 Comparator.comparing(...)

    假设我有一个这样的域模型 class Lecture Course course getters class Course Teacher teacher int studentSize getters class Teacher int
  • 如何在haskell中获取变量名称

    我来到 haskell 时有一些 c 背景知识 想知道是否有类似的 define print a printf s d n a a int a 5 print a 应该打印 a 5 这是 augustss 提到的 TH 解决方案 LANGU
  • lambda 表达式的“类型”可以表达吗?

    将 lambda 表达式视为可调用对象的 语法糖 是否可以表达未命名的基础类型 一个例子 struct gt bool operator int l int r return l gt r Now int l int r return l
  • 你能识别 Haskell 程序中的无限列表吗? [复制]

    这个问题在这里已经有答案了 可能的重复 如何判断列表是否是无限的 https stackoverflow com questions 7371730 how to tell if a list is infinite 在Haskell中 你
  • Haskell:IORef 的性能

    我一直在尝试在 Haskell 中编码一个需要使用大量可变引用的算法 但与纯粹的惰性代码相比 它 也许并不奇怪 非常慢 考虑一个非常简单的例子 module Main where import Data IORef import Contr
  • 这个对自身单位的列表理解是如何工作的?

    在 haskell IRC 频道中有人问 是否有一种简洁的方法来定义一个列表 其中第 n 个条目是之前所有条目的平方和 我认为这听起来像一个有趣的谜题 递归定义无限列表是我真正需要练习的事情之一 所以我启动了 GHCi 并开始尝试递归定义
  • 如何确定 std::function 的参数数量?

    我有以下问题 假设您想编写一个可以采用 lambda 表达式的通用函数 我知道如果参数是 std function 类型 那么我不仅可以使用 lambda 还可以使用函数 甚至可以使用函数指针 所以第一步 我做了以下事情 void prin
  • Haskell - lambda 表达式

    我试图了解什么是有用的以及如何在 Haskell 中实际使用 lambda 表达式 我不太明白使用 lambda 表达式相对于定义函数的约定方式有何优势 例如 我通常会执行以下操作 let add x y x y 我可以简单地打电话 add
  • Haskell 对于 Web 应用程序来说足够成熟吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • std::Optional 的转发引用构造函数的约束

    std optional截至目前 有 8 个构造函数 如下所示 也在这里http en cppreference com w cpp utility 可选 可选 http en cppreference com w cpp utility
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 首先对列表中最长的项目进行排序

    我正在使用 lambda 来修改排序的行为 sorted list key lambda item item lower len item 对包含元素的列表进行排序A1 A2 A3 A B1 B2 B3 B 结果是A A1 A2 A3 B
  • 纯 Haskell 代码需要线程池吗?

    In 现实世界 Haskell 第 28 章 软件事务内存 http book realworldhaskell org read software transactional memory html 开发了一个并发网络链接检查器 它获取网
  • 构造微积分中的“Refl”东西?

    在语言中 例如Agda Idris or Haskell对于类型扩展 有一个 键入类似于以下内容的内容 data a b where Refl a a a b意思是a and b是相同的 这样的类型可以定义在结构演算 https en wi
  • Haskell:需要了解 Functor 的签名

    有人能给我解释一下 Functor 的签名吗 Prelude gt info Functor class Functor f gt where fmap a gt b gt f a gt f b lt a gt f b gt f a 我不明
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • RankN多态性和令人发指的克莱斯利之箭

    我不明白为什么 demobind1 的定义会产生一些编译器错误 它看起来像一个愚蠢的翻转 但不知何故 LANGUAGE GADTs LANGUAGE RankNTypes ScopedTypeVariables TypeOperators

随机推荐

  • 在 main() 之外处理 argc 和 argv

    如果我想将用于处理命令行参数的大部分代码保留在 main 之外 以便组织和更具可读性的代码 那么最好的方法是什么 void main int argc char argv lots of code here I would like to
  • 引用没有强名称的程序集

    有没有办法在没有强名称的情况下引用库 当我在引用中添加对程序集的引用并重建解决方案时 一切都很好 但是当我从此程序集解决方案调用该类时 它不会构建 输出表明引用的程序集应该具有强名称 最好的解决方案是什么 强命名库并不可取 我认为您遇到的问
  • Json.Net 可以嵌入到可执行文件中吗?

    我设置了 嵌入互操作类型 属性Netwonsoft Json图书馆到true它返回一个错误 Cannot embed interop types from assembly c path packages Newtonsoft Json 9
  • 在 JSPX 文件中包含 JS 文件(JQuery)

    我正在 Eclipse 中创建一个动态 Web 项目 几乎从头开始 并创建了一个 JSPX 文件 将其放置在 我打算使用Jquery UI 可排序我发现使用 JSPX 只有第一个脚本在 Firefox 和 IE 中加载
  • 如何使用Opencv轮廓单向描述线点

    我正在使用opencvsfindContour找到描述由线 而不是多边形 组成的图像的点 如下所示 cv findContours src contours hierarchy cv RETR EXTERNAL cv CHAIN APPRO
  • 在 javascript 中迭代颜色

    我想列出 css 中使用的所有颜色的列表 但它们似乎以 16 进制格式存储 我认为这样的事情可能会起作用 但它并没有达到我想要的效果 for x x lt 100 x color x toString 16 在 JavaScript 中 您
  • 如何重新启动独立的 Adob​​e Air/Flex 应用程序

    如何让独立的 Adob e Air Flex 应用程序自行重启 它不适用于以下建议的解决方案 http www colettas org p 267 任何帮助都会很棒 Thanks 你好亲爱的我已经修复了 Flex 4 6 的这个方法 pa
  • 日期时间格式如 HH:mm 24 小时,不含 AM/PM

    我在这里搜索关于将 16 20 这样的字符串转换为 DateTime 类型而不丢失格式 我说我不想添加 dd MM yyy 或秒或 AM PM 因为 db 只是接受这种格式 我还尝试过文化 提前致谢 只需为您的日期时间提供日期格式即可 st
  • 如何使用谷歌材料图标作为类而不是 标签

    根据指南中的谷歌材料网站我们必须在 中使用材质图标i 标签 问题是如何将图标添加为很棒的字体 就像是 Class material icons face 代替 i class material icons face i 是的 您可以使用 a
  • Visual C++ 易失性

    Visual C 中 易失性 的 MSDN 文档表明 除了确保读取始终从内存中读取以及写入始终相应地写入之外 写入具有 释放语义 读取具有 获取语义 易失性 的 C 规范包括第二部分 不要进行疯狂的优化 但不包括第一部分 内存栅栏 Visu
  • 装饰器对代码的特定行而不是整个方法进行计时?

    让我们假设一个简单的方法 def test method a 1 b 10000 c 20000 sum1 sum range a b sum2 sum range b c return sum1 sum2 要使用装饰器计时此方法 一个简单
  • __LINE__ __FILE__ 或 qml 中的类似函数

    我正在尝试打印调用者函数 行号和文件名 而不会在 QML 中出于正常调试目的抛出错误 我可以打印调用者函数名称 如下所示 console log Caller Function Name arguments callee caller na
  • 以编程方式滚动 EditText

    我正在编写一个简单的凯撒加密活动 屏幕上有两个 EditText 一个是明文 一个是加密的 下面是加密 EditText 的一个示例 明文文本与之类似
  • 增加录制音频的音量输出

    我正在尝试在 Android 中制作一个通话录音应用程序 我正在使用扬声器录制上行链路和下行链路音频 我面临的唯一问题是音量太低 我已使用 AudioManager 将设备的音量增加到最大值 但不能超过该值 我首先使用MediaRecord
  • 修改使用 from ... import * 导入的模块中的变量

    考虑以下代码 main py From toolsmodule import database foo toolsmodule database mydatabase 看起来 这在每个模块中创建了一个具有不同内容的变量 如何从 main 修
  • 仅 Android 3.x WebView 文本选择 + JavaScript

    问题域 基于 Android WebView 的 ePub 格式阅读器 我们需要可通过 JavaScript 方法访问的文本突出显示 即打开 关闭 保存并通过电子邮件发送等 如果我的理解有误 请知情者指正 在 WebView 上选择文本时
  • Ruby Symbol#to_proc 在 1.9.2-p180 中泄漏引用?

    好的 这是我第二次尝试使用 Sinatra 应用程序调试内存问题 我相信这次我已经将其固定为简单的示例代码 看来当我过滤数组时 map some method 它会导致该数组中的项目无法被垃圾收集 运行等效的 map x x some me
  • 在 CLion 中设置 ROS 包

    我正在使用 CLion C IDE 来编辑 ROS 包 我可以通过打开CMakeLists txt文件 但是 我收到一个错误 FATAL ERROR find package catkin 失败 在工作区和 CMAKE PREFIX PAT
  • 需要帮助理解合并冲突示例

    我正在遵循一本书中的示例 该示例没有显示解决合并冲突的步骤 正如这篇文章中提到的 该教程对我不起作用 在本地系统上模拟多个用户 提交者所以 我什至无法学习合并 以下是从书中复制的步骤 现在打开空白participants txt文件并将以下
  • 在 Haskell 中简单输入 lambda 演算失败

    我是 Haskell 的新手 所以如果这个问题没有太大意义 我深表歉意 我希望能够在 Haskell 中实现简单类型的 lambda 表达式 这样当我尝试将一个表达式应用于另一个表达式时wrongtype 结果不是类型错误 而是一些设置值