我通过执行从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)
这似乎是提出类型系统的合理要求。我想为ToJSON
,提供演示一个MyType f
个实例,我可以为ToJSON (f a)
提供ToJSON a
个• 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)’
。在逻辑表示法中,这就像是说我可以证明(P(a)⇒P(f(a)))⇒P(h(f))对于某些属性 P 。这似乎很适合我。
不幸的是,我的语法错误如下:
JSONable
看起来QuantifiedConstraints提案会提供此语法,但尚未实现。
我可以尝试通过实现自己的类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)
约束的所有函数。
据我所知,在这种情况下最好的权衡是简单地放弃并编写显式实例:
Private Sub ComboBox2_Change()
On Error Resume Next
Dim myRange As Range
Set myRange = Worksheets("cash").Range("BF:BH")
Price.Value = Application.WorksheetFunction.VLookup(ComboBox2.Value, myRange, 2, 0)
End Sub
这是否真的与语言一样强大?所需的实例是否只是形成错误?或者实际上是否可以在Haskell中为现有的类型类声明这样的实例?
答案 0 :(得分:10)
在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 f
的{{1}}约束的方法,但您也可以使用关注newtype(ToJSON 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)