在 Haskell 中模拟路径依赖类型

2024-01-17

这是我想做的事情的一个简化示例。假设你有一个HList对:

let hlist = HCons (1, "1") (HCons ("0", 2) (HCons ("0", 1.5) HNil))

现在我想写一个函数replaceAll它将用相同类型的第一个“值”替换给定类型的所有“键”。例如,与HList上面我想替换所有String键与"1"这是类型的第一个值String发现于HList

 replaceAll @String hlist =
    HCons (1, "1") (HCons ("1", 2) (HCons ("1", 1.5) HNil))

这似乎需要路径相关的类型,以便“提取”第一对的类型,并能够使用它来指导第二步中键的替换,但我不知道如何在 Haskell 中对其进行编码。


这是一个证明搜索问题(“查找String在此列表中”),因此您可以预期解决方案将涉及类型类 Prolog。我将回答您的问题的更简单版本(即“找到first的发生String") 并让您了解如何根据您的具体用例进行调整。

由于我们正在进行证明搜索,因此让我们首先写下我们将要搜索的证明对象。

data Contains a as where
    Here :: Contains a (a ': as)
    There :: Contains a as -> Contains a (b ': as)

类型的值Contains a as是一个你可以找到的建设性证据a在类型级别列表中as。从结构上来说,Contains就像一个自然数(比较There (There Here) with S (S Z)) 识别位置a在列表中as。为了证明这一点a is in as你给出它的索引。

例如,您可以replace中给定位置的元素HList与相同类型的新元素。

replace :: a -> Contains a as -> HList as -> HList as
replace x Here (HCons y ys) = HCons x ys
replace x (There i) (HCons y ys) = HCons y (replace x i ys)

我们想要寻找一个a在给定列表中使用类型类 Prolog。有两种情况 - 要么你找到a在列表的头部,或者在尾部的某个地方。 (如果a不在as, using contains会因“无实例”错误而失败。)理想情况下,我们会编写如下内容:

class CONTAINS a as where
    contains :: Contains a as

instance CONTAINS a (a ': as) where
    contains = Here

instance CONTAINS a as => CONTAINS a (b ': as) where
    contains = There contains  -- recursively call `contains` on the sublist

但这不符合重叠实例规则。在实例搜索期间不会检查实例上下文和类型相等性 - 阐述者不会回溯 - 因此这两个实例都不比另一个实例更具体。

幸运的是有一个众所周知的解决方案 https://wiki.haskell.org/GHC/AdvancedOverlap对于这个问题。它涉及使用封闭类型族来告诉a and b分开。您定义一个辅助类CONTAINS'有一个额外的参数,在本例中是Bool告诉你是否a可以在头部找到as.

class CONTAINS' (eq :: Bool) a (as :: [*]) where
    contains' :: Contains a as

然后,您为以下情况定义实例:eq is True or False。阐述者可以区分这些实例,因为True and False明显不同。请注意,步骤案例递归调用CONTAINS.

instance CONTAINS' True a (a ': as) where
    contains' = Here

instance CONTAINS a as => CONTAINS' False a (b ': as) where
    contains' = There contains

最后你定义你的CONTAINS实例而言CONTAINS',并使用结果== http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Type-Equality.html,一个封闭类型族,它测试其参数是否相等,以选择一个实例。

instance CONTAINS' (a == b) a (b ': as) => CONTAINS a (b ': as) where
    contains = contains' @(a == b)

(这是布尔类型族极少数可接受的用途之一。)

现在你可以使用CONTAINS就像任何其他课程一样。当你尝试实例化时a and asGHC 将尝试寻找a inside as,以及contains方法将返回其索引。

example :: Contains Int '[Bool, Int, Char]
example = contains

-- "no instance for CONTAINS"
failingExample :: Contains String '[Bool, Int, Char]
failingExample = contains

这是一个相当简单的例子,代码已经相当混乱了。您绝对可以以相同的方式处理问题中的示例,但总而言之,我不相信静态检查值得在这种情况下如此复杂。您是否考虑过基于Typeable?

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

在 Haskell 中模拟路径依赖类型 的相关文章

  • 不同编程语言中的浮点数学

    我知道浮点数学充其量可能是丑陋的 但我想知道是否有人可以解释以下怪癖 在大多数编程语言中 我测试了 0 4 到 0 2 的加法会产生轻微的错误 而 0 4 0 1 0 1 则不会产生错误 两者计算不平等的原因是什么 在各自的编程语言中可以采
  • 如何在Haskell中实现词法分析器和解析器

    我在这里得到了这段代码 它是用Haskell结构的命令式编程语言编写的程序 所以问题是 我如何为这种语言实现词法分析器和解析器 该程序被定义为一系列语句有 6 种类型 goto write stop if goto 和 int int n
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • 构造微积分中的“Refl”东西?

    在语言中 例如Agda Idris or Haskell对于类型扩展 有一个 键入类似于以下内容的内容 data a b where Refl a a a b意思是a and b是相同的 这样的类型可以定义在结构演算 https en wi
  • RankN多态性和令人发指的克莱斯利之箭

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

    尝试对两个值求和 其中只有一个为负值 例如 1 and 2 soma Float gt Float gt Float soma x1 x2 x1 x2 结果出现错误 为什么
  • 无法证明与路径相关类型的等价性

    为什么最后一个summon编译失败 我该怎么做才能让它编译 import java time LocalDateTime LocalTime trait Circular T type Parent given localTimeCircu
  • Erlang 中的非终止函数类型

    我正在学习 Erlang 并尝试使用 Dialyzer 在可能的情况下获得最大的类型安全性 有一点不太明白 什么是类型非终止的函数以及如何表示它 spec 有人能解释一下吗 永远循环且永不终止的函数具有返回类型no return 该返回类型
  • 强制类型差异

    在 Scala 中 我可以在编译时强制执行类型相等 例如 case class Foo A B a A b B implicit ev A B scala gt Foo 1 2 res3 Foo Int Int Foo 1 2 scala
  • 在 ghci 下执行 `(read "[Red]") :: [Color]` 时会发生什么?

    我正在阅读以下小节现实世界 Haskell 第 6 章 类型类 http book realworldhaskell org read using typeclasses html关于一个实例Read for Color 它实现了reads
  • C# 静态类型不能用作参数

    public static void SendEmail String from String To String Subject String HTML String AttachmentPath null String Attachme
  • 如何使用foldr为列表创建显示实例?

    我想为我的数据类型 我的列表 编写自己的显示实例 到目前为止 我的方法是有效的 但我总是在末尾有一个逗号 我已经尝试用最后一个元素启动折叠并将其从列表中删除 但它很麻烦而且不起作用 有没有更简单的方法来获得正确的解决方案 实际 1 2 3
  • 如何在 Haskell Pipes 中将两个 Consumer 合并为一个?

    我使用Haskell流处理库pipes https hackage haskell org package pipes编写一个命令行工具 每个命令行操作都可以将结果输出到stdout并记录到stderr with pipes API I n
  • 未推断扩展接口的通用类型

    在下面的示例中 Typescript 可以推断出类型T在方法中foo从传递给它的参数bar 但它并没有推断出类型R 感觉应该如此 因为它知道类型T还有那个T extends I
  • Haskell 中的所有内容都存储在 thunk 中吗,甚至是简单的值?

    以下值 表达式 函数的 thunk 在 Haskell 堆中是什么样子的 val 5 is val a pointer to a box containing 5 add x y x y result add 2 val main prin
  • 管道 - 将多个来源/生产者合并为一个

    我正在使用读取文件sourceFile 但我还需要在处理操作中引入随机性 我认为最好的方法是拥有一个这样的制片人 Producer m StdGen ByteString 其中 StdGen 用于生成随机数 我打算让生产者执行 source
  • Pandas 将 NULL 读取为 NaN 浮点数而不是 str [重复]

    这个问题在这里已经有答案了 给定文件 cat test csv a b c NULL d e f g h i j k l m n 其中第三列被视为str 当我对列执行字符串函数时 pandas已阅读NULLstr 作为一个NaN float
  • Haskell 中多核编程的现状如何?

    Haskell 中多核编程的现状如何 现在有哪些项目 工具和库可用 有哪些经验报道 2009年至2012年期间 发生了以下事件 2012 从 2012 年开始 并行 Haskell 状态更新开始出现在并行 Haskell 摘要 http w
  • 使用 Haskell 绘制图表

    是否可以使用 Haskell 绘制一个简单的图表 你们中的任何人都可以告诉我该怎么做吗 该图应至少包含 3 个点 Haskell 图表 https github com timbod7 haskell chart似乎不错 The wiki
  • Haskell / cabal 包的解决方法受到 Nix 和 Cabal 的限制?

    我最近开始开发反射平台 https github com reflex frp reflex platform 有一些额外的配置类似于优秀的反射项目骨架 https github com ElvishJerricco reflex proj

随机推荐

  • Emacs:仅在迷你缓冲区中禁用行截断

    我在用IDO模式 http www emacswiki org emacs InteractivelyDoThings用于 Emacs 23 中的文件和缓冲区切换 如果目录中有超过一行的文件 以下选项允许调整迷你缓冲区的大小 setq re
  • Windows 中的自签名证书无需 makecert?

    我们有一个收缩包装类型的 Windows 服务器应用程序 我们需要在服务器上创建一个自签名证书以供某些 WCF Web 服务使用 从我们在网络上的搜索来看 Microsoft PlatformSDK 中的 makecert 实用程序似乎无法
  • Python 类中的公共变量?

    我现在正在自学 Python 课程 并发现了这个页面 http www tutorialspoint com python python classes objects htm http www tutorialspoint com pyt
  • Flutter:如何获取 Firestore 中集合的所有文档名称

    我使用 Firestore 在 Flutter 中制作了一个应用程序 现在我将浏览集合中的所有文档 我想获取文档名称 id 和文档字段 并对其执行某些操作 我已经制作了一个显示数据的列表视图 但我无法用它做一些事情 例如 将其添加到列表或其
  • 多线程应用程序执行 onclickBtn 后挂起

    我正在 javaFx 中编写一个天气应用程序 从 openweather org 获取数据 从 openweather 获取 JSON 的整个代码工作正常 也将 JSON 数据转换为对象 我使用lambda表达式来实现Runnable in
  • Python 习语与多次调用 os.path.dirname 获得相同的结果?

    我发现自己需要在源树中获取 python 文件的父目录 该源树是具有一定规律性的多个目录 必须多次调用 dirname 很笨拙 我环顾四周 很惊讶没有找到关于此的帖子 一般场景是 import os path as op third deg
  • 如何在 MSVC 下检测 C++11 的 noexcept 功能?

    我正在使用 C 库 该库的最低要求是 C 03 我在 Visual Studio 2015 下收到一些关于抛出析构函数的警告 algparam h 271 warning C4297 AlgorithmParametersBase Algo
  • 前端和后端可以共享同一个package.json吗?

    我有一个小型个人项目 正在一个存储库中开发 后端是 Node js 服务器 前端是 Vue js 应用程序 我希望它们共享相同的 package json 我想这样做的唯一原因是因为我想使用 scripts 一个通用的 package js
  • 如何解决松散耦合/依赖注入和富域模型之间的冲突?

    Edit 这不是理论层面的冲突 而是实施层面的冲突 另一个编辑 问题在于域模型不作为纯数据 DTO 而不是更丰富 更复杂的对象映射 其中 Order 具有 OrderItems 和一些calculateTotal 逻辑 具体问题是 例如 该
  • 在下次调用之前中断 spring 调度程序任务

    我有一个 Spring Boot 应用程序 它将成为我们想要触发的其他几个进程的编排服务 我目前使用 Spring Scheduling 从数据库动态提取 cron 来设置它 我引入了一个休息方法来触发从数据库中提取新的 cron 信息的过
  • 在 c++11 中全局修复种子

    我正在尝试使用新的c
  • 如何捕获和查看 Cortex-M4 MCU 上的 ITM 跟踪信息?

    我想捕获 解码和查看 Cortex M4 MCU 在我的例子中是 Atmel SAM4S 的 ITM 跟踪信息 特别是 我想捕获与板上其他信号相关的异常和用户跟踪数据 即在同一时间线上显示所有信号和跟踪信息 这可以通过以下步骤完成 将调试器
  • AngularJS 指令绑定具有多个参数的函数

    我在将控制器中定义的函数与指令中的回调函数绑定时遇到一些问题 我的代码如下所示 在我的控制器中 scope handleDrop function elementId file console log handleDrop called 然
  • 在sql server中对加密列建立索引

    我将患者健康信息存储在 SQL Server 2012 数据库中 当我搜索病人的姓名时 他们的名字是加密的 所以搜索速度非常慢 如何在加密列上添加索引 我在 varbinary 字段上使用对称密钥加密 256 位 AES 患者的名字 姓氏
  • Maven 版本控制最佳实践 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 更改 Maven 项目版本 发布此版本然后返回到的最佳方法是什么 SNAPSHOT发展 目前我正在做以下事情 检索当前版本 最有可能的是SNAP
  • 如何绘制多列的条形图 3D 投影

    我有一个表 其中包含根据两个不同参数的三个不同时间特征 我想在 x 轴和 y 轴上绘制这些参数 并在 z 轴上显示三个不同时间的条形 我创建了一个简单的条形图 其中绘制了其中一个时间特征 import numpy as np import
  • 是否可以将数据从 DelegatingHandler 传递到 ASP.NET Web API 中的控制器?

    我正在实现一个与授权相关的 DelegatingHandler 其中我从数据库加载 api 用户 调用者 配置文件 当授权成功时 我想将此实例传递给控制器 否则我必须再次加载它 有没有办法在不使用会话或依赖存储库缓存的情况下执行此操作 Ht
  • 当网格被过滤时,Kendo 工具栏 AddNew 按钮不起作用

    我有一个小的剑道网格 设置如下 以一种令人难以置信的神秘方式 添加新 的控制器操作 即BatchCreate仅当您在单击 添加新项 后单击另一个命令按钮时才会调用 例如 a 单击 添加新的 什么也没有发生 b 重新加载页面 点击 Add N
  • 了解第 3 方 iframe 安全性?

    Facebook 和其他公司提供了一些小的 iframe 片段 我可以将它们放入我的网站中 例子 我想知道的是 如果我把这段代码放在我这边 他们加载到我页面中的代码可以访问我页面的 DOM 吗 如果是的话 我看到一些安全问题 同样 Face
  • 在 Haskell 中模拟路径依赖类型

    这是我想做的事情的一个简化示例 假设你有一个HList对 let hlist HCons 1 1 HCons 0 2 HCons 0 1 5 HNil 现在我想写一个函数replaceAll它将用相同类型的第一个 值 替换给定类型的所有 键