使用DataKinds的FromJSON实例 [英] FromJSON instance with DataKinds

查看:44
本文介绍了使用DataKinds的FromJSON实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用TypeLits对数据类型进行JSON反序列化时,我陷入了以下问题:

Trying to do the JSON de-serialisation for a data type with TypeLits, I get stuck with the following problem:


Couldn't match type ‘n’ with ‘2’
      ‘n’ is a rigid type variable bound by
        the instance declaration at test.hs:14:10
      Expected type: aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
                       (X n)
        Actual type: aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
                       (X 2)

在下面的示例中,如何在 FromJSON 实例中普遍允许 Nat 的正确语法:

How would be the correct syntax to allow Nat generically in the FromJSON instance in the following example:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

import GHC.TypeLits
import Data.Aeson
import Control.Monad (mzero)

data X (n :: Nat) where
  A :: Integer -> X 1
  B :: Integer -> X 2

instance FromJSON (X n) where
  parseJSON (Object o) = do
      v <- o .: "val"
      t <- o .: "type"
      case t of
        "a" -> return $ A v
        "b" -> return $ B v
  parseJSON _       = mzero

推荐答案

由于您显然不知道在编译时要反序列化的类型,因此确切的类型需要隐藏在一个存在的对象中,然后通过模式匹配进行恢复.我通常使用通用的 Some 类型来隐藏幻像类型.

Since you obviously cannot know the type you are going to deserialize at compile time, the exact type needs to be hidden in an existential and then restored via pattern matching. I usually use a generic Some type to hide phantom types.

{-# LANGUAGE PolyKinds #-}

data Some (t :: k -> *) where
    Some :: t x -> Some t

现在您可以将实例写为

instance FromJSON (Some X) where
    parseJSON (Object o) = do
        v <- o .: "val"
        t <- o .: "type"
        case (t :: String) of
          "a" -> return $ Some $ A v
          "b" -> return $ Some $ B v
    parseJSON _       = mzero

但是,您还需要启用 FlexibleInstances 扩展名.

However, you also need to enable the FlexibleInstances extension.

这篇关于使用DataKinds的FromJSON实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆