gpt4 book ai didi

haskell - 编写 `(forall a . Class a => Class (f a)) => Class (Type f)` 形式的实例

转载 作者:行者123 更新时间:2023-12-02 01:50:16 26 4
gpt4 key购买 nike

我通过从 MyType Maybe 执行自然转换来在我的一个程序中执行默认分辨率。至MyType Identity .我想推导出 ToJSON这些类型的实例。我知道MaybeIdentity有实例ToJSON a => ToJSON (Maybe a)ToJSON a => ToJSON (Identity a) .

我想声明以下形式的一个实例:

instance (forall a . ToJSON a => ToJSON (f a)) => ToJSON (MyType f)

这似乎是向类型系统提出的合理要求。我想演示一个 ToJSON MyType f 的实例,前提是我总能得到 ToJSON (f a)对于每个 ToJSON a .用逻辑符号表示,这就像说我可以证明某些属性 P 的 (P(a) ⇒ P(f(a))) ⇒ P(h(f))。这对我来说似乎很好。

不幸的是,我得到以下语法错误:
• Illegal polymorphic type: forall a. ToJSON a => ToJSON (f a)
A constraint must be a monotype
• In the context: (forall a. ToJSON a => ToJSON (f a))
While checking an instance declaration
In the instance declaration for ‘ToJSON (GpgParams f)’

它看起来像 QuantifiedConstraints提案将提供此语法,但尚未实现。

我可以尝试通过实现我自己的类 JSONable 来解决这个限制。 .
class JSONable f where
jsonize :: f a -> Value

default jsonize :: (ToJSON a, ToJSON (f a)) => f a -> Value
jsonize = toJSON

不幸的是,这意味着放弃标准库中所有使用需要 ToJSON 的函数。约束。

据我所知,在这种情况下,最好的权衡是简单地放弃并为以下内容编写显式实例:
instance ToJSON (MyType Maybe)
instance ToJSON (MyType Identity)

这真的和语言一样强大吗?所需的实例只是格式错误吗?或者实际上是否可以在 Haskell 中为现有类型类声明这样的实例?

最佳答案

在 QuantifiedConstraints 到来之前,有一个标准的解决方案来编码像 forall a. ToJSON a => ToJSON (f a) 这样的约束。 ,这看起来就像你提到的,但我们不必放弃使用 ToJSON 的函数约束。
forall a. ToJSON a => ToJSON (f a)是对 f 的约束:我们可以将其定义为类型类。幸运的是,aeson already has ToJSON1 .

class ToJSON1 f where  -- encoding of `forall a. ToJSON a => ToJSON (f a)`
...

并使用该类有一个功能
toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value

如果有任何类型 F有一个实例 ToJSON1 F ,那么预计它的 ToJSON实例等价于
instance ToJSON a => ToJSON (F a) where
toJSON = toJSON1

这样 ToJSON1 F确实编码 forall a. ToJSON a => ToJSON1 (F a) .

aeson 似乎缺少的一件事是解决 ToJSON (f a) 的方法。给定的约束 ToJSON1 fToJSON a ,但您也可以使用以下新类型( Identity 的高级版本)对其进行编码:
newtype Id1 f a = Id1 { unId1 :: f a }

instance (ToJSON1 f, ToJSON a) => ToJSON (Id1 f a) where
toJSON = toJSON1 . unId1

然后定义 ToJSON (MyType f) ,我们可以先申请 coerce :: MyType f -> MyType (Id1 f) .
import Data.Coerce

instance ToJSON1 f => ToJSON (MyType f) where
toJSON = (...) . (coerce :: MyType f -> MyType (Id1 f))
{- in "(...)" we can use functions that require "ToJSON (Id1 f a)", which is informally equivalent to "ToJSON (f a)" -}

关于haskell - 编写 `(forall a . Class a => Class (f a)) => Class (Type f)` 形式的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49541473/

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