首页 > 解决方案 > 有没有比较/更改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}

标签: haskell

解决方案


正如其他人在评论中提到的那样,创建不同的记录来保存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_到另一种类型。

老实说,博客文章在解释这一点方面会比我做得更好。我觉得这个主题很有趣,但我自己对它还是很陌生。

希望这有帮助!:-)


推荐阅读