gpt4 book ai didi

haskell - aeson 中的 FromJSON1 和 ToJSON1 是做什么用的?

转载 作者:行者123 更新时间:2023-12-05 00:48:41 30 4
gpt4 key购买 nike

爱生提供 FromJSON1 ToJSON1 类型类。这些类似于 Eq1 Show1 Data.Functor.Classes 中定义的类模块。

我对 Eq1 的理解和 Show1类是需要它们能够表达对转换器参数的约束,而不使用像 FlexibleContexts 这样的扩展。和 UndecidableInstances .
Data.Functor.Classes 中文档中的示例模块如下:

假设我们有一个充当转换器的数据类型:T .例如,让它与 IdentityT 同构。 :

data T f a = T (f a)

那种 T如下:
T :: (* -> *) -> * -> *

如果有 Eq1 f 的实例,可以在写 Eq1的时候使用 T f 的实例:
instance Eq1 f => Eq1 (T f) where
liftEq :: (a -> b -> Bool) -> T f a -> T f b -> Bool
liftEq eq (T fa1) (T fa2) = liftEq eq fa1 fa2

如果我们有 Eq1 f 的实例, 一个 Eq a 的实例,以及 Eq1 T f 的实例以上是在范围内,我们可以很容易地写 Eq T f a 的实例:
instance (Eq1 f, Eq a) => Eq (T f a) where
(==) :: T f a -> T f a -> Bool
(==) = eq1
eq1的类型定义如下:
eq1 :: (Eq1 h, Eq a) => h a -> h a -> Bool

在我们上面的例子中, h变成 T f ,所以 eq1 的类型可以认为如下:
eq1 :: Eq a => T f a -> T f a -> Bool

现在, Eq1 , Show1等类是有意义的。似乎更容易编写 Eq 的实例, Show等用于变压器。

但是,我想知道 FromJSON1 的类型是什么?和 ToJSON1用于Aeson?我很少有我想在 JSON 之间转换的转换器。

我最终更改为 JSON 的大多数数据类型都是普通类型(不是类型构造函数)。也就是说,类型为 * .我也使用像 Maybe 这样的类型用一种 * -> * .

但是,我不认为我经常创建 ToJSONFromJSON变压器的实例,例如 T多于。什么是经常用于往返 JSON 的转换器?我错过了一些有用的变压器吗?

最佳答案

Eq1提供了另一个您在说明中没有讨论过的特性:它允许您编写一个调用 (==) 的函数。在许多不同的类型上,不必提前知道您将在哪些类型上使用它。

我将举一个玩具示例;希望你能看穿这个例子的明显无用的原因 Eq1给你一些有趣的力量。

想象一下,您想要创建一个在分支因子上参数化的树,因此您通过子容器对其进行参数化。所以值可能如下所示:

{-# LANGUAGE GADTs #-}
data Tree m a where
Branch :: Tree m (m a) -> Tree m a
Leaf :: a -> Tree m a

例如,我可以得到二叉树 Tree Pair , 三叉树与 Tree Triple ,手指树与 Tree TwoThree , 和玫瑰树与 Tree [] , 其中 data Pair a = Pair a a , data Triple a = Triple a a a , 和 data TwoThree a = Two a a | Three a a a .现在我想写一个 Eq例如这个。如果我们只依赖 Eq约束,我们无法到达我们想去的地方。咱们试试吧:
instance Eq (Tree m a) where
Leaf a == Leaf a' = a == a'
Branch t == Branch t' = t == t'
_ == _ = False

自然地,GHC 提示它不知道如何比较 aa'为了平等。所以添加 Eq a上下文:
instance Eq a => Eq (Tree m a) where ...

现在GHC提示它不知道如何比较 m a s 表示 Branch 中的平等案子。说得通。
instance (Eq a, Eq (m a)) => Eq (Tree m a) where ...

还是不行!现在执行 (==) :: Tree m a -> Tree m a -> Bool递归调用 (==) :: Tree m (m a) -> Tree m (m a) -> Bool在其 Branch情况,因此必须提供上下文 (Eq (m a), Eq (m (m a)))进行递归调用。好的,让我们将它添加到实例上下文中......
instance (Eq a, Eq (m a), Eq (m (m a))) => Eq (Tree m a) where ...

还是不行。现在递归调用必须证明更多的东西!我们真正想说的是,如果我们有 Eq b , 那么我们有 Eq (m b) , 对于所有 b s 而不仅仅是特定的 a被用作 Tree的第二个参数。
instance (Eq a, (forall b. Eq b => Eq (m b))) => Eq (Tree m a) where ...

当然,这在 Haskell 中完全不是一回事。但是 Eq1给了我们:
instance Eq1 m => Eq1 (Tree m) where
liftEq (==) (Leaf a) (Leaf a') = a == a'
liftEq (==) (Branch t) (Branch t') = liftEq (liftEq (==)) t t'
liftEq (==) _ _ = False

instance (Eq1 m, Eq a) => Eq (Tree m a) where
(==) = eq1

这里 Eq1 m约束服务于我们之前要求的角色,即所有 (Eq a, Eq (m a), Eq (m (m a)), ...)是可能的。
ToJSON1FromJSON1类起到类似的作用:它们给你一个单一的约束,你可以给它一个可能无限的 ToJSON 集合。和 FromJSON约束,以便您可以选择 ToJSONFromJSON您需要以数据驱动的方式进行约束,并保证它是可用的。

关于haskell - aeson 中的 FromJSON1 和 ToJSON1 是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49188247/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com