我通过执行自然转换MyType Maybe
来执行我的一个程序中的默认分辨率MyType Identity
.我想ToJSON
为这些类型派生一个实例.我知道Maybe
并且Identity
有实例ToJSON a => ToJSON (Maybe a)
和ToJSON a => ToJSON (Identity a)
.
我想声明以下形式的实例:
instance (forall a . ToJSON a => ToJSON (f a)) => ToJSON (MyType f)
Run Code Online (Sandbox Code Playgroud)
这似乎是提出类型系统的合理要求.我想表现出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)’
Run Code Online (Sandbox Code Playgroud)
看起来QuantifiedConstraints提议会提供这种语法,但它尚未实现.
我可以尝试通过实现自己的类来解决这个约束JSONable
.
class JSONable f where
jsonize :: f a -> Value
default jsonize :: (ToJSON a, ToJSON (f a)) => f a -> Value
jsonize = toJSON
Run Code Online (Sandbox Code Playgroud)
不幸的是,这意味着放弃使用需要ToJSON
约束的标准库中的所有函数.
据我所知,在这种情况下最好的权衡是简单地放弃并编写显式实例:
instance ToJSON (MyType Maybe)
instance ToJSON (MyType Identity)
Run Code Online (Sandbox Code Playgroud)
它是否真的像语言一样强大?所需的实例是否只是形成错误?或者实际上是否可以在Haskell中为现有的类型类声明这样的实例?
Li-*_*Xia 10
在QuantifiedConstraints到达之前,有一个标准的解决方案来编码约束forall a. ToJSON a => ToJSON (f a)
,就像你提到的那样,但我们不必放弃使用ToJSON
约束的函数.
forall a. ToJSON a => ToJSON (f a)
是一个约束f
:我们可以将其定义为类型类.幸运的是,艾森已经拥有了ToJSON1
.
class ToJSON1 f where -- encoding of `forall a. ToJSON a => ToJSON (f a)`
...
Run Code Online (Sandbox Code Playgroud)
并且使用该类有一个功能
toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value
Run Code Online (Sandbox Code Playgroud)
如果任何类型F
具有实例ToJSON1 F
,则预期其ToJSON
实例等效于
instance ToJSON a => ToJSON (F a) where
toJSON = toJSON1
Run Code Online (Sandbox Code Playgroud)
所以这ToJSON1 F
确实编码forall a. ToJSON a => ToJSON1 (F a)
.
有一两件事,似乎遗漏对埃宋是解决办法ToJSON (f a)
的约束给定ToJSON1 f
和ToJSON a
,但你也可以使用下面的NEWTYPE(中高kinded版本进行编码Identity
):
newtype Id1 f a = Id1 { unId1 :: f a }
instance (ToJSON1 f, ToJSON a) => ToJSON (Id1 f a) where
toJSON = toJSON1 . unId1
Run Code Online (Sandbox Code Playgroud)
然后定义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)" -}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
236 次 |
最近记录: |