haskell - 有没有比较/更改haskell中的一个/两个记录的规范方法?
问题描述
我想比较haskell中的两条记录,而不是一遍又一遍地为记录的所有元素定义记录的数据类型的每次更改以及2个数据的每个函数。
我阅读了有关镜头的信息,但找不到示例,也不知道从哪里开始阅读文档。
示例,不起作用:
data TheState = TheState { number :: Int,
truth :: Bool
}
initState = TheState 77 True
-- not working, example:
stateMaybe = fmap Just initState
-- result should be:
-- ANewStateType{ number = Just 77, truth = Just True}
同样,我想比较这两种状态:
state2 = TheState 78 True
-- not working, example
stateMaybe2 = someNewCompare initState state2
-- result should be:
-- ANewStateType{ number = Just 78, truth = Nothing}
解决方案
正如其他人在评论中提到的那样,创建不同的记录来保存Maybe
字段的版本并进行手动转换很可能更容易。但是,有一种方法可以让仿函数以更自动化的方式映射到您的字段。
它可能比您想要的要复杂得多,但可以使用一种称为Higher Kinded Data ( HKD ) 的模式和一个名为barbies
.
这是一篇关于这个主题的精彩博客文章:https ://chrispenner.ca/posts/hkd-options
这是我在您的具体示例中使用HKD的尝试:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
-- base
import Data.Functor.Identity
import GHC.Generics (Generic)
-- barbie
import Data.Barbie
type TheState = TheState_ Identity
data TheState_ f = TheState
{ number :: f Int
, truth :: f Bool
} deriving (Generic, FunctorB)
initState :: TheState
initState = TheState (pure 77) (pure True)
stateMaybe :: TheState_ Maybe
stateMaybe = bmap (Just . runIdentity) initState
这里发生的事情是,我们将记录的每个字段都包装在一个 customf
中。我们现在可以选择参数化TheState
的内容以包装每个字段。现在,普通记录的所有字段都包含在Identity
. 但是您也可以轻松获得其他版本的记录。该bmap
函数让您将转换从一种类型映射TheState_
到另一种类型。
老实说,博客文章在解释这一点方面会比我做得更好。我觉得这个主题很有趣,但我自己对它还是很陌生。
希望这有帮助!:-)
推荐阅读
- html - jsPDF 将 HTML 字符串转换为 PDF
- node.js - 在 nodejs 中使用 sequelize mock 为模型编写测试
- javascript - javascript中while循环中的奇怪行为
- javascript - 不使用热重载时无法解析组件
- java - 这有什么问题
- python-3.x - 无法在 python (AWS Lambda) 中使用“lambda-git”库使用“diff”命令
- javascript - 尝试分派类型时不再调用函数
- php - unserialize() 请在第二个参数中指定允许反序列化的类
- python - 检查 azure blob 存储文件夹的 len 导致函数无法运行
- r - 在 R 中使用 glmmboot 和未来包的警告