如何在haskell中将函数类型序列化为json?

2024-03-17

data Task = Task
    { id :: String
    , description :: String
    , dependsOn :: [String]
    , dependentTasks :: [String]
    } deriving (Eq, Show, Generic, ToJSON, FromJSON)

type Storage = Map String Task

s :: Storage
s = empty

addTask :: Task -> Storage -> Storage
addTask (Task id desc dep dept) = insert id (Task id desc dep dept)

removeTask :: String -> Storage -> Storage
removeTask tid = delete tid

changes = [addTask (Task "1" "Description" [] []), removeTask "1"]

main = putStrLn . show $ foldl (\s c -> c s) s changes

假设我有以下代码。我想存储changes列表在 json 文件中。但我不知道如何使用 Aeson 来做到这一点,除了编写自定义解析器之外,显然肯定有更好的方法来做到这一点。就像也许使用语言扩展来派生(Generic, ToJSON, FromJSON) for addTask and removeTask etc...

编辑。对于所有说“你不能序列化函数”的人。

阅读此问题答案的评论。

函数的实例显示 https://stackoverflow.com/questions/10551210/instance-show-for-function

也就是说,不可能定义 Show 来真正为您提供更多 ?有关该功能的详细信息。 – 路易斯·沃瑟曼 2012 年 5 月 12 日 14:51

就是这样。它可以显示类型(通过 Typeable 给出);或者它可以显示一些输入和输出(如 QuickCheck 中所做的那样)。

编辑2。好吧,我知道序列化中不能有函数名称。但这可以通过 Haskell 模板来完成吗?我看到 aeson 通过模板 Haskell 支持序列化,但作为 Haskell 的新手,不知道如何做到这一点。


仔细阅读字里行间,这里反复出现的一个问题是:“为什么我不能(轻松地)序列化函数?”答案——有几个人提到过,但没有明确解释——是 Haskell 致力于引用透明性。引用透明度表示您可以用定义的值替换定义(反之亦然),而无需更改程序的含义。

现在,假设我们有一个假设serializeFunction,在存在此代码的情况下:

foo x y = x + y + 3

会有这样的行为:

> serializeFunction (foo 5)
"foo 5"

我想如果我也当着所有人的面声称这一点,你不会太强烈地反对

bar x y = x + y + 3

我们会“想要”这种行为:

> serializeFunction (bar 5)
"bar 5"

现在我们有一个问题,因为通过引用透明度

  serializeFunction (foo 5)
= { definition of foo }
  serializeFunction (\y -> 5 + y + 3)
= { definition of bar }
  serializeFunction (bar 5)

but "foo 5"不相等"bar 5".

明显的后续问题是:为什么我们要求引用透明度?至少有两个很好的理由:首先,它允许像上面这样的等式推理,从而减轻重构的负担;其次,它减少了所需的运行时信息量,从而提高了性能。

当然,如果您能够提出尊重引用透明度的函数表示,那就不会造成任何问题。以下是这个方向的一些想法:

  • 打印函数的类型

    instance (Typeable a, Typeable b) => Show (a -> b) where
        show = show . typeOf
    -- can only write a Read instance for trivial functions
    
  • 打印输入输出行为 http://hackage.haskell.org/package/universe-reverse-instances-1.0/docs/src/Data-Universe-Instances-Show.html函数的(也可以被读回 http://hackage.haskell.org/package/universe-reverse-instances-1.0/docs/src/Data-Universe-Instances-Read.html)

  • 创建一个将函数与其名称相结合的数据类型,然后打印该名称

    data Named a = Named String a
    instance Show (Named a) where
        show (Named n _) = n
    -- perhaps you could write an instance Read (Map String a -> Named a)
    

    (另请参阅云哈斯克尔 http://hackage.haskell.org/package/distributed-process为了更完整地实现这个想法)

  • 构造一个代数数据类型,它可以表示您关心的所有表达式,但仅包含已经具有的基本类型Show实例并序列化该实例(例如,如其他答案中所述)

但是打印裸函数的名称与引用透明度相冲突。

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

如何在haskell中将函数类型序列化为json? 的相关文章

随机推荐

  • jQuery 模拟点击选项卡并执行代码

    下面的代码 当我单击选项卡时 我会发布帖子并在选项卡中显示结果 在某些情况下 我想强制选择选项卡 但不仅选择该选项卡 而且选择该选项卡 执行单击它时执行的代码 在我的示例中 我喜欢选择第二个选项卡 jLikeToSet 1 并执行代码 po
  • 如何将一个android studio项目合并到另一个android studio项目中

    我有两个独立的 android 应用程序项目 它们是在 android studio 中制作的 我正在尝试将项目 1 合并到项目 2 中 使其成为一个应用程序 我将如何去做呢 我知道如何在 eclipse 中执行此操作 但不知道如何在 an
  • 使用 dart::ffi 从 Dart 包中调试 C++ 代码

    我正在用 C 开发一个包 用于 Flutter 应用程序 因此在 Dart 中 使用飞镖 菲菲 https dart dev guides libraries c interop我想知道除了记录消息之外 是否有更好的方法来调试 逐步 变量监
  • 从返回堆栈恢复片段时的savedInstanceState

    我可以用吗savedInstanceState 删除片段时保存状态 然后从返回堆栈弹出片段时恢复状态 当我从返回堆栈恢复片段时 savedInstanceState 包始终为空 现在 应用程序流程是 创建片段 gt 删除片段 添加到后台堆栈
  • MySQL 可以对单个查询使用多个索引吗?

    想象一个具有多列的表 例如 id a b c d e 我通常选择通过id但是 客户端应用程序中有多个查询对列的子集使用各种条件 当MySQL在多列上使用多个WHERE条件对单表执行查询时 它真的可以利用在不同列上创建的索引吗 或者使其快速的
  • 以编程方式构建 SQL 查询的可靠方法

    我必须求助于 ORM 不足的原始 SQL 使用 Django 1 7 问题是大多数查询最终有 80 90 相似 我无法找出一种稳健且安全的方法来构建查询而不违反可重用性 字符串连接是唯一的出路吗 即使用构建无参数查询字符串if else条件
  • Cloud Functions FCM 预期 OAuth 2 访问令牌

    因此 自 7 月 29 日以来 我注意到我的 Firebase Cloud Functions 在尝试发送 FCM 消息时抛出错误 错误 请求缺少所需的身份验证凭据 预期的 OAuth 2 访问令牌 登录 cookie 或其他有效身份验证
  • Json字符串化范围错误

    我从 API 得到的结果如下 id 1 area zone T aisle side E col 1 level 0 position 0 name T E 1 id 2 area zone T aisle side E col 60 le
  • Objective C UITableView - 更改单元格高度后表格单元格显示错误的内容

    我正在尝试在 xcode 中构建一个应用程序 它除了其他应用程序之外还读取 rss 提要并显示帖子 我是 Objective C 的新手 有时发现它有点困难 我使用 NSMutableArray 来获取检索到的故事 帖子 每个故事都由一个
  • 使用 RVM 安装 Ruby 2.1.3 时出错

    我正在尝试使用 RVM 安装 Ruby 2 1 3 我安装了最新版本的 XCode 并且全新安装了 rvm 我基本上在做 rvm autolibs brew rvm install ruby 2 1 3 一切看起来都工作正常 但随后我收到此
  • CGContext 文本绘制在 iPhone 4 上无法按比例放大

    我正在尝试创建一个可以在 iPhone 4 上很好地缩放的应用程序 目前 它的大部分都可以完美缩放 除了一个关键部分 我在 CALayer 中的 drawInContext 方法内绘制的文本 这是我的代码 void drawInContex
  • 挂钩事件 Outlook VSTO 在主线程上继续工作

    我开发了一个 Outlook VSTO 插件 有些任务应该在后台线程上完成 通常 检查本地数据库中的某些内容或调用网络请求 阅读了几篇文章后 我放弃了在后台线程中调用 Outlook 对象模型 OOM 的想法 我有一些 wpf 控件 并且我
  • 在 django-rest-framework 中创建一个带有关系的rest api

    在 django rest framework 中创建一个rest api 我有2张桌子 拳头表 用户 id PK Name varchar 255 第二个表 地址 id PK address varchar 255 city id int
  • 如何将多个 UIBarButtonItem 添加到 UINavigationBar?

    我想添加很多UIBarButtonItem s to a UINavigationbar 不仅仅是左右按钮 logoButton UIBarButtonItem alloc initWithTitle A Button style UIBa
  • WP7 - 防止 RestSharp 缓存

    我在 Windows Phone 7 1 项目中使用 RestSharp 我的问题是 RestSharp 总是缓存响应数据 Example 我第一次发送请求时 它正确返回数据 经过一些删除操作后 我再次发送该请求 但响应似乎与第一次相同 没
  • 从结账后挂钩中检索分支名称

    当在 Git 中从一个分支切换到另一个分支时 是否有任何方法可以从 post checkout 挂钩中检索两个分支的名称 所以假设我要运行以下两个命令 git branch branch a branch b master git chec
  • 以递归函数的形式返回

    我想了解如何在 C 中使用递归 但我不明白如何return在其中工作 请考虑以下代码 int recur int i printf recur i d n i if i lt 3 recur i 1 return 10 else if i
  • SHA512 哈希值在 android、php 和 javascript 上有所不同

    我正在使用 SHA512 哈希在我的应用程序与其后端之间传输一些加密数据 然而 我遇到了一个奇怪的情况 不知道是什么原因造成的 因此 我测试了以下设置 安卓 2x SHA512 Android 1x SHA512 gt CryptoJS 1
  • Snackbar 和其他动画在某些 Android 设备上停止工作

    我有一个非常奇怪的问题 我无法弄清楚 直到最近我才成为一个问题 但我似乎无法恢复以防止它 另一个奇怪的事情是它可以在某些设备上运行 而在其他设备上则不能 问题是动画 其中一个特别是小吃店 小吃栏应该上下动画 但事实并非如此 它只是显示然后隐
  • 如何在haskell中将函数类型序列化为json?

    data Task Task id String description String dependsOn String dependentTasks String deriving Eq Show Generic ToJSON FromJ