如何在具有自定义类型类约束的GADT上实现fromJSON?

约翰·沃克

我有以下GADT:

{-# LANGUAGE GADTs #-}

data LogProtocol a where
  Message :: String -> LogProtocol String
  StartRun :: forall rc. (Show rc, Eq rc, Titled rc, ToJSON rc, FromJSON rc) 
   => rc -> LogProtocol rc
  ... and many more...

toJSON很简单,没有显示。fromJSON的实现基于:

这个SO问题这个Blog发布-模式2

如下:

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}

-- tag type is used in to/ from JSON to reduce the use of magic strings
data LPTag = MessageT |
             StartRunT |
             ... and many more...
             deriving (Show, Eq, Enum)

tagList :: Enum a => [a]
tagList = enumFrom $ toEnum 0

$(deriveJSON defaultOptions ''LPTag) 

-- a wrapper to hide the a type param in the GADT
data Some (t :: k -> *) where
  Some :: t x -> Some t

instance FromJSON (Some LogProtocol) where

parseJSON :: Value -> Parser (Some LogProtocol)
parseJSON v@(Object o) =
  let 
    tag :: Maybe LPTag 
    tag = do 
      t <- (HML.lookup "type" o) 
      parseMaybe parseJSON t 

    failMessage :: [Char]
    failMessage = toS $ "Could not parse LogProtocol no type field or type field value is not a member of specified in: " 
                    <> (show(tagList :: [LPTag])) 
                    <> show v

  in 
    maybe  
      (fail failMessage )
      (
        \case 
          MessageT -> Some <$> (Message <$> o .: "txt")    
          StartRunT -> Some <$> (StartRun <$> o .: "runConfig")
      )
      tag        

parseJSON wrng = typeMismatch "LogProtocol" wrng

'''Message'''的情况很好。我遇到的问题是诸如以下的错误:

* No instance for (Titled x2) arising from a use of `StartRun'
* In the first argument of `(<$>)', namely `StartRun'
  In the second argument of `(<$>)', namely
    `(StartRun <$> o .: "runConfig")'
  In the expression: Some <$> (StartRun <$> o .: "runConfig")

在数据构造函数中我有自己的类型类约束(例如Titled)的任何地方,编译器都说“否”。有办法解决吗?

Li-yao Xia

存在类型是一种反模式,尤其是在您需要反序列化的情况下。StartRun应该包含一个具体类型。反序列化仍然需要一种具体的类型,因此您也可以将StartRun专门化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

自定义UnmarshalYAML,如何在自定义类型上实现Unmarshaler接口

SpecFlow-如何在具有自定义类型的实体上设置测试数据

如何在引导程序中具有特定类的所有元素上定义自定义工具提示

如何在自定义类型上放置非空约束?

如何在同一层次结构上具有页面和自定义帖子类型

我应该如何实现具有某些(相同)类型的实例的自定义计数器?

为具有两个相同类型类的自定义数据类型实现应用函子

具有自定义类类型的键的哈希图

如何实现自定义类型上的fmt :: Display?

如何在Keras中实现具有多个输入的自定义层

如何在Keras中实现具有动态形状的自定义输出层?

如何使用自动映射器映射具有多个自定义属性类型的类

如何在自定义元素上实现ngModel?

如何在具有自定义循环和自定义设计的wordpress上使用同位素?

在具有多个类型类的自定义数据类型上使用仿函数/求和论?

如何在Postgres C函数中将数组返回为具有自定义类型的数组?

如何在自定义属性指令中获取具有数字类型的输入的值

json = null 在自定义 JsonConverter 中的 fromJSON 方法中“具有多个构造函数的冻结类”

在Go中创建具有约束的自定义类型

如何在自定义类型上构建堆

如何在 AWS lex 上拥有自由文本自定义插槽类型

如何在开始屏幕上创建具有自定义颜色的图块

Java EE-如何在具有自定义注释的方法上注入方法参数

如何在C#中的自定义按钮上具有默认的BackColor值

如何在具有自定义输入功能的元素上添加onclick事件

如何在discord.py上为具有自定义状态的成员赋予角色

如何在QMainWindow上显示自定义的QSplitter类

具有自定义类型的HashSet

具有自定义类型的列表