如何从支持某些 API 的函数返回非具体值?

2024-01-09

我正在两个模型之间构建 API。我不在乎它是否返回 [] 或 Seq 或任何可折叠的都可以。但如果我尝试这样做,就会出错。

module Main where
import Prelude hiding (foldr)
import Data.Foldable
import Data.Sequence

data Struct = Struct

main = do
  print $ foldr (+) 0 $ list Struct
  print $ foldr (+) 0 $ listFree Struct


listFree :: Foldable f => a -> f Int
listFree s = singleton 10

class TestClass a where
  list :: Foldable f => a -> f Int

instance TestClass Struct where
  list s = singleton 10

listFree 和 list 定义都会给出相同的错误:

TestFoldable.hs:19:12:
Could not deduce (f ~ [])
from the context (Foldable f)
  bound by the type signature for
             list :: Foldable f => Struct -> f Int
  at TestFoldable.hs:19:3-15
  `f' is a rigid type variable bound by
      the type signature for list :: Foldable f => Struct -> f Int
      at TestFoldable.hs:19:3
In the expression: [10]
In an equation for `list': list s = [10]
In the instance declaration for `TestClass Struct'

这是为什么?完成我在这里想做的事情的“正确”方法是什么?

我想要完成的是向调用者隐藏实现。实际的数据结构可能是 Seq、IntMap 或其他任何结构,而且很可能不是列表。

我收到的回复是“只需返回一个列表”。但这意味着转变,不是吗?如果它是一个 1,000,000 个元素结构怎么办?仅仅因为 API 的限制而将其转换为中间数据结构似乎是一个糟糕的解决方案。

这是一个普遍的问题。如何获得符合某些 API 的返回值?隐藏具体的实现,以便实现者可以自由选择最适合他们的结构,并且可以更改它而无需更改 API 的用户。

另一种说法是:如何返回接口而不是具体类型?

结束语:

Stack Overflow 上的 Haskell 社区是(Superlative Compliment c => forall c.c)

存在量化似乎是解决这种情况的通用方法。

另一种需要考虑的可能性是为客户端返回折叠的闭包,这不是通用解决方案,但可能适用于这种特定情况,可能会避免存在解决方案所需的额外包装器值:

list :: a -> ((Int -> b -> b) -> b -> b)
list = \f a0 -> foldr f a0 (singleton 10)

这是为什么?

方式Foldable f => a -> f Int does not意味着该函数可能会返回它想要的任何可折叠对象。这意味着该函数将返回用户想要的任何类型。 IE。如果用户在需要列表的上下文中使用该函数,则该函数应该起作用,并且如果他在需要 Seq 的上下文中使用该函数,该函数也应该起作用。由于您的定义显然不是这种情况,因此它与其类型不匹配。

完成我在这里想做的事情的“正确”方法是什么?

最简单的方法是让你的函数返回一个列表。

但是,如果您确实需要向用户隐藏您正在使用列表的事实,最简单的方法是围绕列表创建一个包装类型,而不是导出该类型的构造函数。 IE。就像是:

module Bla (ListResult(), list) where
data ListResult a = ListResult [a]

instance Foldable (ListResult a) where
    foldr op s (ListResult xs) = foldr op s xs

list s = ListResult [10]

现在,如果用户导入您的模块,它可以折叠 ListResult,因为它是可折叠的,但它无法解压它以获取列表,因为构造函数未导出。所以如果你以后改变ListResult的定义为data ListResult a = ListResult (Seq a) and list还可以使用Seq而不是列表,该更改对用户来说是完全不可见的。

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

如何从支持某些 API 的函数返回非具体值? 的相关文章

  • Haskell:IORef 的性能

    我一直在尝试在 Haskell 中编码一个需要使用大量可变引用的算法 但与纯粹的惰性代码相比 它 也许并不奇怪 非常慢 考虑一个非常简单的例子 module Main where import Data IORef import Contr
  • 为什么 ZipList 不是 List 的默认应用实例

    我目前正在学习 Haskell 中的应用程序 如果我没记错的话 列表有两个不同的应用实例 List and ZipList 第二个被定义为包装列表值的新类型 这ZipList应用实例对我来说似乎更直观 这可能是一个愚蠢的问题 但有具体原因吗
  • 如何通过“cabal build”或“stack build”构建带有图标的项目

    我想构建一个带有图标的可执行文件 通过谷歌搜索 我发现这里的说明 https wiki haskell org Setting an executable icon 但它只能通过编译源文件来工作ghc 如果我想构建一个具有可执行文件的项目c
  • 不同编程语言中的浮点数学

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

    我知道 ST monad 有点像 IO 的弟弟 而 IO 又是添加了状态 monadRealWorld魔法 我可以想象状态 也可以想象 RealWorld 以某种方式放入 IO 中 但每次我写一个类型签名ST the sST monad 的
  • 如何在Haskell中实现词法分析器和解析器

    我在这里得到了这段代码 它是用Haskell结构的命令式编程语言编写的程序 所以问题是 我如何为这种语言实现词法分析器和解析器 该程序被定义为一系列语句有 6 种类型 goto write stop if goto 和 int int n
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 关于“没有绑定的类型签名”的错误

    我在 Haskell 中遇到 ASCII 问题 fromEnum Char gt Int toEnum Int gt Char offset Int offset fromEnum A fromEnum a toUpper Char gt
  • 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 我不明
  • 如何同时将透镜(或任何其他光学器件)视为吸气剂和设置剂?

    我正在尝试编写一个通用记录更新程序 它允许人们轻松更新记录中的字段existing记录 字段形状相似incoming记录 这是我到目前为止所拥有的 applyUpdater fields existing incoming let gett
  • 如何让 do 块提前返回?

    我正在尝试使用 Haskell 抓取网页并将结果编译到一个对象中 如果出于某种原因 我无法从页面获取所有项目 我想停止尝试处理页面并提前返回 例如 scrapePage String gt IO scrapePage url do doc
  • 管道 - 将多个来源/生产者合并为一个

    我正在使用读取文件sourceFile 但我还需要在处理操作中引入随机性 我认为最好的方法是拥有一个这样的制片人 Producer m StdGen ByteString 其中 StdGen 用于生成随机数 我打算让生产者执行 source
  • 如何从具有函数依赖关系的类型类中获取和使用依赖类型?

    如何从具有函数依赖关系的类型类中获取和使用依赖类型 为了澄清并给出我最近的尝试的一个例子 从我正在编写的实际代码中最小化 class Identifiable a b a gt b where if you know a you know
  • 在列表中查找元素及其索引

    我需要让列表的两个元素都满足谓词and这些元素的索引 我可以通过以下方式实现这一点 import Data List findIndices list Int list 3 2 4 1 9 indices findIndices gt 2
  • 为什么我不能声明推断类型?

    我有以下内容 runcount Eq a Num b gt a gt b runcount runcountacc 0 runcountacc Eq a Num b gt b gt a gt b runcountacc n runcount
  • 使用 Parsec 解析正则表达式

    我正在尝试通过实现一个小型正则表达式解析器来学习秒差距 在 BNF 中 我的语法类似于 EXP EXP LIT EXP LIT 我尝试在 Haskell 中实现这一点 expr try star lt gt try litE lt gt l
  • 使用默认值压缩而不是删除值?

    我正在 haskell 中寻找一个函数来压缩两个长度可能不同的列表 我能找到的所有 zip 函数都只是删除列表中比其他列表长的所有值 例如 在我的练习中 我有两个示例列表 如果第一个比第二个短 我必须用 0 填充 否则我必须使用 1 我不允
  • Haskell 为替代的 Either 数据类型定义 Functor 实例

    通过 Typeclassopedia 获得一些使用类型类的路由 想要替代Either的一个实例Functor 但即使检查定义Either作为一个例子Functor总是给我带来麻烦 有这个 但不会编译 data Alt a b Success
  • Haskell 中的内部爆炸模式是否总是强制使用外部构造函数?

    在 Haskell 中 是否存在对于数据类型 LANGUAGE BangPatterns import Control DeepSeq data D D Int 实例 instance NFData D where rnf D 与具有另一个
  • 为什么 GHC 在这里推断出单态类型,即使禁用了单态限制?

    这是由解析 f f pure 的类型 https stackoverflow com questions 55388119 resolving the type of f f pure 55388309 noredirect 1 comme

随机推荐

  • 如何使用 ffmpeg 删除所有元数据?

    我有输入文件 infile mp3该文件包含元数据 艺术家 流派等 我尝试删除所有元数据以输出 wav file 是的 我找到了选项 地图元数据 1 但输出出乎我意料 ffmpeg i infile mp3 acodec pcm s16le
  • SQLite数据库最大存储容量

    SQLite 数据库中最多可以存储多少条记录 有什么限制吗 如果数据超出此限制 会给出什么类型的错误 整个系统会失败 还是会发生什么 基于this http developer android com guide topics data d
  • PhpStorm LESS 观察程序配置

    我正在使用 PhpStorm 8 处理一些 LESS 文件 variables less导入自styles less 当我保存时variables less only a variables css正在制作中 如何将观察者配置为仅转译sty
  • 是否有提交空选择多个的标准客户端行为?

    http www w3 org TR html401 interact forms html edef SELECT http www w3 org TR html401 interact forms html edef SELECT 不指
  • 使用 java 中的 scala.collection.immutable.Set 的示例

    有熟悉 Scala 的人知道我如何使用scala collection immutable Set http www scala lang org docu files api scala collection immutable Set
  • 实体框架 6 代码优先 - 存储库实现是一个好的实现吗?

    我即将使用存储库和工作单元实现 Entity Framework 6 设计 周围有很多文章 我不确定最好的建议是什么 例如 我真的很喜欢这里实现的模式 出于文章中建议的原因here http codefizzle wordpress com
  • 我应该在事务中包含 SELECT 吗?

    当使用数据库事务对多个更新进行分组时 我是否也应该在事务中包含 SELECT 例如 假设我 得到一个记录 使用记录中的数据检查该记录的编辑权限 更新一些记录 更新一些其他记录 我应该在 获取记录 阶段之前开始交易 还是在更新前后开始交易 我
  • iframe 中的 Javascript window.opener

    我正在尝试使用弹出窗口脚本文件中的 window opener 引用来访问弹出窗口的开启器 考虑 popup html 中包含的以下脚本 http localhost test popup html 当不涉及 iframe 时 此方法有效
  • 获取 li 元素的文本

    ul class leftbutton li Sample 1 li li Sample 2 li li Sample 3 li li Sample 4 li li Sample 5 li ul 我想获取 id menu selected
  • 创建类似于 iBook 或 Stanza 应用程序的 ePub 阅读器的最佳方法 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 gnuplot 中为 xticlabels 提供自定义字符串参数?

    假设我有一个包含三列的数据文件 我希望能够更改 x 轴标签 经过一番谷歌搜索后我发现xticlabels 但问题是它似乎只接受列号作为参数 用于 ex 绘图xticlabels 3 用第三列标记标签 我希望能够把类似的东西 1 2作为该函数
  • 合并重复的数组项

    我有一个哈希数组 array keyword gt A total value gt 50 keyword gt B total value gt 25 keyword gt C total value gt 40 keyword gt A
  • 进程友善度(优先级)设置对 Linux 没有影响

    我编写了一个测试程序 其中仅包含一个无限循环 其中包含一些 内部计算 并且不执行 I O 操作 我尝试启动该程序的两个实例 其中一个具有高 尼斯值 另一个具有低尼斯值 sudo nice n 19 taskset 1 test sudo n
  • 来自 github 的 Git 存储库空绿色文件夹

    我正在从 github 中提取 git 存储库 当我克隆存储库时 会出现一个空文件夹 其中应该包含一个项目 由于其他项目引用了该文件夹 当我浏览 github 上的存储库时 该文件夹显示为绿色 我有什么遗漏的吗 我在用 git clone
  • 在 Xcode 上管理代码片段的最佳方法是什么?

    我已经爱上了 Visual Studio 的代码片段工具包 Xcode 上有类似的东西吗 您还可以看看this https stackoverflow com questions 20420 any resharper equivalent
  • 如何在Windows上安装PLV8?

    我正在尝试将其安装在我的 PostgreSQL 服务器上 http code google com p plv8js wiki PLV8 http code google com p plv8js wiki PLV8这些文档看起来很棒 但问
  • 断开连接的图表上缺少悬停标记

    我遇到了一个问题 我不确定这是 highcharts 插件中的错误还是编程错误 我使用空值来绘制仅包含一个系列的断开线图 但这似乎是悬停标记的问题 其中一些标记 在第一行的顶部和第二行的底部 似乎没有出现 代码很简单 但我找不到导致此问题的
  • Python - 来自 stdin 的 HTTP post [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我每秒左右从 bash 命令 ibeacon scan 获取这种格式的数据 ibeacon scan b stdin py Out
  • 带 -a 的路径对于 bash 函数没有意义

    这是我的 bash 函数 push gt cd var www html wp gt git init gt git add gt git commit am 1 gt git push f origin master gt 我想执行它 d
  • 如何从支持某些 API 的函数返回非具体值?

    我正在两个模型之间构建 API 我不在乎它是否返回 或 Seq 或任何可折叠的都可以 但如果我尝试这样做 就会出错 module Main where import Prelude hiding foldr import Data Fold