Haskell 是否可以从数据类型中删除函数类型,以允许deriveJSON?

Haskell 是否可以从数据类型中删除函数类型,以允许deriveJSON?,haskell,generic-programming,aeson,Haskell,Generic Programming,Aeson,我有几个代表应用程序状态的数据类型。在数据类型的不同位置,我有嵌入式函数或一元操作,例如 data Foo = Foo Int (ActionM String) data Bar = Bar Foo (Maybe Bar) (ActionM ()) 我需要将这些数据类型中的大多数编码为json,以便将其发送到浏览器进行显示。使用deriveJSON(来自Aeson包)不起作用,因为无法派生ActionM的实例。然而,我实际上并不希望这些信息被发送出去。我目前有一种方法可以工作,但基本上是复制粘

我有几个代表应用程序状态的数据类型。在数据类型的不同位置,我有嵌入式函数或一元操作,例如

data Foo = Foo Int (ActionM String)
data Bar = Bar Foo (Maybe Bar) (ActionM ())
我需要将这些数据类型中的大多数编码为json,以便将其发送到浏览器进行显示。使用deriveJSON(来自Aeson包)不起作用,因为无法派生ActionM的实例。然而,我实际上并不希望这些信息被发送出去。我目前有一种方法可以工作,但基本上是复制粘贴全套数据类型并手动删除嵌入的ActionM字段

我(想我)需要一些东西中的一个。或者

  • 这是一种告诉deriveJSON忽略它无法理解的字段,并可能将它们解析回未定义的
    。据我所知,这是不存在的
  • 一种在删除这些字段的情况下自动生成并行数据类型集的方法。所以我想写一些像
applyMagic条

回来

data Foo' = Foo' Int
data Bar' = Bar' Foo' (Maybe Bar')

这有可能吗?我该怎么做呢?

这是一个过于简单的解决方案,但是你不能像这样做吗

data Foo' = Foo' Int

type Foo = (ActionM String, Foo')
当您想要序列化时,只需获取元组的第二个元素

元组是的一个实例,因此您还可以使用函数,如
ask
extract

编辑。
Bar
是一种更复杂的情况,因为它是递归类型。但可以使用comonad变压器进行处理:

import Data.Functor.Identity
import Data.Bifunctor (second)
import Control.Comonad -- from 'comonad'
import Control.Comonad.Hoist.Class
import Control.Comonad.Trans.Cofree -- from 'free'

-- Orphan ComonadHoist instance that will likely be added in future
-- versions of free
instance Functor f => ComonadHoist (CofreeT f) where
    cohoist g = CofreeT . fmap (second (cohoist g)) . g . runCofreeT

type Bar = CofreeT Maybe ((,) (ActionM ())) Foo
type Bar' = Cofree Maybe Foo'

applyMagic :: Bar -> Bar'
applyMagic = cohoist (Identity . extract) . fmap extract
CofreeT Maybe((,)(ActionM()))Foo
是用
ActionM()
值注释的
Foo
值的非空列表

Cofree-Maybe-Foo'
是一个非空的
Foo'
值列表,没有额外的注释(
Cofree-Maybe-Foo
CofreeT-Maybe-Identity-Foo'
的同义词,其中
Identity
起到了次要的作用。)

要将一个转换为另一个,
applyMagic
首先使用
fmap extract
将所有
Foo
s转换为
Foo'
s,然后使用from
comonadjust
删除
CofreeT
下面的“注释层”


一般来说,带有“额外上下文”的值通常可以用comonads建模。

如果
ActionM
data
newtype
您可以为它定义一个
ToJSON
实例,将其编码为一些简单的JSON值(例如0或“”),那么您可以自动派生
Foo
的ToJSON。它仍然会包含一个额外的简单值,但它会为您节省大量的工作。您如何将此扩展到包含
Bar
?@ajp我已将我的答案扩展到包含
Bar